1 /* Copyright (C) 2018-2021 Greenbone Networks GmbH
2 *
3 * SPDX-License-Identifier: AGPL-3.0-or-later
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20 * @file gmp_base.c
21 * @brief GVM GMP layer: Base facilities.
22 *
23 * GMP base facilities used by all modules, but not exported for users of the GMP
24 * layer (i.e. gmpd.c).
25 */
26
27 #include "gmp_base.h"
28 #include "manage.h"
29
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <gvm/base/strings.h>
34
35 #undef G_LOG_DOMAIN
36 /**
37 * @brief GLib log domain.
38 */
39 #define G_LOG_DOMAIN "md gmp"
40
41 /**
42 * @brief Find an attribute in a parser callback list of attributes.
43 *
44 * @param[in] attribute_names List of names.
45 * @param[in] attribute_values List of values.
46 * @param[in] attribute_name Name of sought attribute.
47 * @param[out] attribute_value Attribute value return.
48 *
49 * @return 1 if found, else 0.
50 */
51 int
find_attribute(const gchar ** attribute_names,const gchar ** attribute_values,const char * attribute_name,const gchar ** attribute_value)52 find_attribute (const gchar **attribute_names,
53 const gchar **attribute_values,
54 const char *attribute_name,
55 const gchar **attribute_value)
56 {
57 while (*attribute_names && *attribute_values)
58 if (strcmp (*attribute_names, attribute_name))
59 attribute_names++, attribute_values++;
60 else
61 {
62 *attribute_value = *attribute_values;
63 return 1;
64 }
65 return 0;
66 }
67
68 /**
69 * @brief Find an attribute in a parser callback list of attributes and append
70 * @brief it to a string using gvm_append_string.
71 *
72 * @param[in] attribute_names List of names.
73 * @param[in] attribute_values List of values.
74 * @param[in] attribute_name Name of sought attribute.
75 * @param[out] string String to append attribute value to, if
76 * found.
77 *
78 * @return 1 if found and appended, else 0.
79 */
80 int
append_attribute(const gchar ** attribute_names,const gchar ** attribute_values,const char * attribute_name,gchar ** string)81 append_attribute (const gchar **attribute_names,
82 const gchar **attribute_values,
83 const char *attribute_name,
84 gchar **string)
85 {
86 const gchar* attribute;
87 if (find_attribute (attribute_names, attribute_values, attribute_name,
88 &attribute))
89 {
90 gvm_append_string (string, attribute);
91 return 1;
92 }
93 return 0;
94 }
95
96 /**
97 * @brief Format XML into a buffer.
98 *
99 * @param[in] buffer Buffer.
100 * @param[in] format Format string for XML.
101 * @param[in] ... Arguments for format string.
102 */
103 void
buffer_xml_append_printf(GString * buffer,const char * format,...)104 buffer_xml_append_printf (GString *buffer, const char *format, ...)
105 {
106 va_list args;
107 gchar *msg;
108 va_start (args, format);
109 msg = g_markup_vprintf_escaped (format, args);
110 va_end (args);
111 g_string_append (buffer, msg);
112 g_free (msg);
113 }
114
115
116 /* Communication. */
117
118 /**
119 * @brief Send a response message to the client.
120 *
121 * @param[in] msg The message, a string.
122 * @param[in] user_send_to_client Function to send to client.
123 * @param[in] user_send_to_client_data Argument to \p user_send_to_client.
124 *
125 * @return TRUE if send to client failed, else FALSE.
126 */
127 gboolean
send_to_client(const char * msg,int (* user_send_to_client)(const char *,void *),void * user_send_to_client_data)128 send_to_client (const char* msg,
129 int (*user_send_to_client) (const char*, void*),
130 void* user_send_to_client_data)
131 {
132 if (user_send_to_client && msg)
133 return user_send_to_client (msg, user_send_to_client_data);
134 return FALSE;
135 }
136
137 /**
138 * @brief Send an XML find error response message to the client.
139 *
140 * @param[in] command Command name.
141 * @param[in] type Resource type.
142 * @param[in] id Resource ID.
143 * @param[in] gmp_parser GMP Parser.
144 *
145 * @return TRUE if out of space in to_client, else FALSE.
146 */
147 gboolean
send_find_error_to_client(const char * command,const char * type,const char * id,gmp_parser_t * gmp_parser)148 send_find_error_to_client (const char* command, const char* type,
149 const char* id, gmp_parser_t *gmp_parser)
150 {
151 gchar *msg;
152 gboolean ret;
153
154 msg = g_markup_printf_escaped ("<%s_response status=\""
155 STATUS_ERROR_MISSING
156 "\" status_text=\"Failed to find %s '%s'\"/>",
157 command, type, id);
158 ret = send_to_client (msg, gmp_parser->client_writer,
159 gmp_parser->client_writer_data);
160 g_free (msg);
161 return ret;
162 }
163
164 /**
165 * @brief Set an out of space parse error on a GError.
166 *
167 * @param [out] error The error.
168 */
169 void
error_send_to_client(GError ** error)170 error_send_to_client (GError** error)
171 {
172 g_debug (" send_to_client out of space in to_client");
173 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
174 "Manager out of space for reply to client.");
175 }
176
177 /**
178 * @brief Set an internal error on a GError.
179 *
180 * @param [out] error The error.
181 */
182 void
internal_error_send_to_client(GError ** error)183 internal_error_send_to_client (GError** error)
184 {
185 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
186 "Internal Error.");
187 }
188
189 /**
190 * @brief Creates a log event entry for a resource action.
191 *
192 * @param[in] type Resource type.
193 * @param[in] type_name Resource type name.
194 * @param[in] id Resource id.
195 * @param[in] action Action done.
196 * @param[in] fail Whether it is a fail event.
197 */
198 static void
log_event_internal(const char * type,const char * type_name,const char * id,const char * action,int fail)199 log_event_internal (const char *type, const char *type_name, const char *id,
200 const char *action, int fail)
201 {
202 gchar *domain;
203
204 domain = g_strdup_printf ("event %s", type);
205
206 if (id)
207 {
208 char *name;
209
210 if (manage_resource_name (type, id, &name))
211 name = NULL;
212 else if ((name == NULL)
213 && manage_trash_resource_name (type, id, &name))
214 name = NULL;
215
216 if (name)
217 g_log (domain, G_LOG_LEVEL_MESSAGE,
218 "%s %s (%s) %s %s by %s",
219 type_name, name, id,
220 fail ? "could not be" : "has been",
221 action,
222 current_credentials.username);
223 else
224 g_log (domain, G_LOG_LEVEL_MESSAGE,
225 "%s %s %s %s by %s",
226 type_name, id,
227 fail ? "could not be" : "has been",
228 action,
229 current_credentials.username);
230
231 free (name);
232 }
233 else
234 g_log (domain, G_LOG_LEVEL_MESSAGE,
235 "%s %s %s by %s",
236 type_name,
237 fail ? "could not be" : "has been",
238 action,
239 current_credentials.username);
240
241 g_free (domain);
242 }
243
244 /**
245 * @brief Creates a log event entry for a resource action.
246 *
247 * @param[in] type Resource type.
248 * @param[in] type_name Resource type name.
249 * @param[in] id Resource id.
250 * @param[in] action Action done.
251 */
252 void
log_event(const char * type,const char * type_name,const char * id,const char * action)253 log_event (const char *type, const char *type_name, const char *id,
254 const char *action)
255 {
256 log_event_internal (type, type_name, id, action, 0);
257 }
258
259 /**
260 * @brief Creates a log event failure entry for a resource action.
261 *
262 * @param[in] type Resource type.
263 * @param[in] type_name Resource type name.
264 * @param[in] id Resource id.
265 * @param[in] action Action done.
266 */
267 void
log_event_fail(const char * type,const char * type_name,const char * id,const char * action)268 log_event_fail (const char *type, const char *type_name, const char *id,
269 const char *action)
270 {
271 log_event_internal (type, type_name, id, action, 1);
272 }
273