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 #ifndef _GVMD_GMP_BASE_H
20 #define _GVMD_GMP_BASE_H
21 
22 #include <glib.h>
23 
24 /**
25  * @brief A handle on a GMP parser.
26  */
27 typedef struct
28 {
29   int (*client_writer) (const char *, void *); ///< Writes to the client.
30   void *client_writer_data;                    ///< Argument to client_writer.
31   int importing;             ///< Whether the current op is importing.
32   int read_over;             ///< Read over any child elements.
33   int parent_state;          ///< Parent state when reading over.
34   gchar **disabled_commands; ///< Disabled commands.
35 } gmp_parser_t;
36 
37 int
38 find_attribute (const gchar **, const gchar **, const char *, const gchar **);
39 
40 int
41 append_attribute (const gchar **, const gchar **, const char *, gchar **);
42 
43 void
44 buffer_xml_append_printf (GString *, const char *, ...);
45 
46 gboolean
47 send_to_client (const char *, int (*) (const char *, void *), void *);
48 
49 gboolean
50 send_find_error_to_client (const char *, const char *, const char *,
51                            gmp_parser_t *);
52 
53 void
54 error_send_to_client (GError **);
55 
56 void
57 internal_error_send_to_client (GError **);
58 
59 /**
60  * @brief Send response message to client and return a given value on error.
61  *
62  * Queue a message in \ref to_client with \ref send_to_client.  On failure
63  * call \ref error_send_to_client on a GError* called "error" and do a return.
64  *
65  * @param[in]   err_ret   Return value on send error.
66  * @param[in]   format    Format string for message.
67  * @param[in]   args      Arguments for format string.
68  */
69 #define SENDF_TO_CLIENT_OR_FAIL_WITH_RETURN(err_ret, format, args...) \
70   do                                                                  \
71     {                                                                 \
72       gchar *msg = g_markup_printf_escaped (format, ##args);          \
73       if (send_to_client (msg, gmp_parser->client_writer,             \
74                           gmp_parser->client_writer_data))            \
75         {                                                             \
76           g_free (msg);                                               \
77           error_send_to_client (error);                               \
78           return err_ret;                                             \
79         }                                                             \
80       g_free (msg);                                                   \
81     }                                                                 \
82   while (0)
83 
84 /**
85  * @brief Send response message to client, returning on fail.
86  *
87  * Queue a message in \ref to_client with \ref send_to_client.  On failure
88  * call \ref error_send_to_client on a GError* called "error" and do a return.
89  *
90  * @param[in]   format    Format string for message.
91  * @param[in]   args      Arguments for format string.
92  */
93 #define SENDF_TO_CLIENT_OR_FAIL(format, args...)             \
94   do                                                         \
95     {                                                        \
96       gchar *msg = g_markup_printf_escaped (format, ##args); \
97       if (send_to_client (msg, gmp_parser->client_writer,    \
98                           gmp_parser->client_writer_data))   \
99         {                                                    \
100           g_free (msg);                                      \
101           error_send_to_client (error);                      \
102           return;                                            \
103         }                                                    \
104       g_free (msg);                                          \
105     }                                                        \
106   while (0)
107 
108 /**
109  * @brief Send response message to client, returning on fail.
110  *
111  * Queue a message in \ref to_client with \ref send_to_client.  On failure
112  * call \ref error_send_to_client on a GError* called "error" and do a return.
113  *
114  * @param[in]   msg    The message, a string.
115  */
116 #define SEND_TO_CLIENT_OR_FAIL(msg)                        \
117   do                                                       \
118     {                                                      \
119       if (send_to_client (msg, gmp_parser->client_writer,  \
120                           gmp_parser->client_writer_data)) \
121         {                                                  \
122           error_send_to_client (error);                    \
123           return;                                          \
124         }                                                  \
125     }                                                      \
126   while (0)
127 
128 void
129 log_event (const char *, const char *, const char *, const char *)
130   __attribute__ ((weak));
131 
132 void
133 log_event_fail (const char *, const char *, const char *, const char *);
134 
135 /* Status codes. */
136 
137 /* HTTP status codes used:
138  *
139  *     200 OK
140  *     201 Created
141  *     202 Accepted
142  *     400 Bad request
143  *     401 Must auth
144  *     404 Missing
145  */
146 
147 /**
148  * @brief Response code for a syntax error.
149  */
150 #define STATUS_ERROR_SYNTAX "400"
151 
152 /**
153  * @brief Response code when authorisation is required.
154  */
155 #define STATUS_ERROR_MUST_AUTH "401"
156 
157 /**
158  * @brief Response code when authorisation is required.
159  */
160 #define STATUS_ERROR_MUST_AUTH_TEXT "Authenticate first"
161 
162 /**
163  * @brief Response code for forbidden access.
164  */
165 #define STATUS_ERROR_ACCESS "403"
166 
167 /**
168  * @brief Response code text for forbidden access.
169  */
170 #define STATUS_ERROR_ACCESS_TEXT "Access to resource forbidden"
171 
172 /**
173  * @brief Response code for a missing resource.
174  */
175 #define STATUS_ERROR_MISSING "404"
176 
177 /**
178  * @brief Response code text for a missing resource.
179  */
180 #define STATUS_ERROR_MISSING_TEXT "Resource missing"
181 
182 /**
183  * @brief Response code for a busy resource.
184  */
185 #define STATUS_ERROR_BUSY "409"
186 
187 /**
188  * @brief Response code text for a busy resource.
189  */
190 #define STATUS_ERROR_BUSY_TEXT "Resource busy"
191 
192 /**
193  * @brief Response code when authorisation failed.
194  */
195 #define STATUS_ERROR_AUTH_FAILED "400"
196 
197 /**
198  * @brief Response code text when authorisation failed.
199  */
200 #define STATUS_ERROR_AUTH_FAILED_TEXT "Authentication failed"
201 
202 /**
203  * @brief Response code on success.
204  */
205 #define STATUS_OK "200"
206 
207 /**
208  * @brief Response code text on success.
209  */
210 #define STATUS_OK_TEXT "OK"
211 
212 /**
213  * @brief Response code on success, when a resource is created.
214  */
215 #define STATUS_OK_CREATED "201"
216 
217 /**
218  * @brief Response code on success, when a resource is created.
219  */
220 #define STATUS_OK_CREATED_TEXT "OK, resource created"
221 
222 /**
223  * @brief Response code on success, when the operation will finish later.
224  */
225 #define STATUS_OK_REQUESTED "202"
226 
227 /**
228  * @brief Response code text on success, when the operation will finish later.
229  */
230 #define STATUS_OK_REQUESTED_TEXT "OK, request submitted"
231 
232 /**
233  * @brief Response code for an internal error.
234  */
235 #define STATUS_INTERNAL_ERROR "500"
236 
237 /**
238  * @brief Response code text for an internal error.
239  */
240 #define STATUS_INTERNAL_ERROR_TEXT "Internal error"
241 
242 /**
243  * @brief Response code when a service is unavailable.
244  */
245 #define STATUS_SERVICE_UNAVAILABLE "503"
246 
247 /**
248  * @brief Response code when a service is down.
249  */
250 #define STATUS_SERVICE_DOWN "503"
251 
252 /**
253  * @brief Response code text when a service is down.
254  */
255 #define STATUS_SERVICE_DOWN_TEXT "Service temporarily down"
256 
257 /**
258  * @brief Expand to XML for a STATUS_ERROR_SYNTAX response.
259  *
260  * @param  tag   Name of the command generating the response.
261  * @param  text  Text for the status_text attribute of the response.
262  */
263 #define XML_ERROR_SYNTAX(tag, text)     \
264   "<" tag "_response"                   \
265   " status=\"" STATUS_ERROR_SYNTAX "\"" \
266   " status_text=\"" text "\"/>"
267 
268 /**
269  * @brief Expand to XML for a STATUS_ERROR_ACCESS response.
270  *
271  * @param  tag  Name of the command generating the response.
272  */
273 #define XML_ERROR_ACCESS(tag)           \
274   "<" tag "_response"                   \
275   " status=\"" STATUS_ERROR_ACCESS "\"" \
276   " status_text=\"" STATUS_ERROR_ACCESS_TEXT "\"/>"
277 
278 /**
279  * @brief Expand to XML for a STATUS_SERVICE_UNAVAILABLE response.
280  *
281  * @param  tag   Name of the command generating the response.
282  * @param  text  Status text.
283  */
284 #define XML_ERROR_UNAVAILABLE(tag, text)       \
285   "<" tag "_response"                          \
286   " status=\"" STATUS_SERVICE_UNAVAILABLE "\"" \
287   " status_text=\"" text "\"/>"
288 
289 /**
290  * @brief Expand to XML for a STATUS_ERROR_MISSING response.
291  *
292  * @param  tag  Name of the command generating the response.
293  */
294 #define XML_ERROR_MISSING(tag)           \
295   "<" tag "_response"                    \
296   " status=\"" STATUS_ERROR_MISSING "\"" \
297   " status_text=\"" STATUS_ERROR_MISSING_TEXT "\"/>"
298 
299 /**
300  * @brief Expand to XML for a STATUS_ERROR_AUTH_FAILED response.
301  *
302  * @param  tag  Name of the command generating the response.
303  */
304 #define XML_ERROR_AUTH_FAILED(tag)           \
305   "<" tag "_response"                        \
306   " status=\"" STATUS_ERROR_AUTH_FAILED "\"" \
307   " status_text=\"" STATUS_ERROR_AUTH_FAILED_TEXT "\"/>"
308 
309 /**
310  * @brief Expand to XML for a STATUS_ERROR_BUSY response.
311  *
312  * @param  tag  Name of the command generating the response.
313  */
314 #define XML_ERROR_BUSY(tag)           \
315   "<" tag "_response"                 \
316   " status=\"" STATUS_ERROR_BUSY "\"" \
317   " status_text=\"" STATUS_ERROR_BUSY_TEXT "\"/>"
318 
319 /**
320  * @brief Expand to XML for a STATUS_OK response.
321  *
322  * @param  tag  Name of the command generating the response.
323  */
324 #define XML_OK(tag)           \
325   "<" tag "_response"         \
326   " status=\"" STATUS_OK "\"" \
327   " status_text=\"" STATUS_OK_TEXT "\"/>"
328 
329 /**
330  * @brief Expand to XML for a STATUS_OK_CREATED response.
331  *
332  * @param  tag  Name of the command generating the response.
333  */
334 #define XML_OK_CREATED(tag)           \
335   "<" tag "_response"                 \
336   " status=\"" STATUS_OK_CREATED "\"" \
337   " status_text=\"" STATUS_OK_CREATED_TEXT "\"/>"
338 
339 /**
340  * @brief Expand to XML for a STATUS_OK_CREATED response with %s for ID.
341  *
342  * @param  tag  Name of the command generating the response.
343  */
344 #define XML_OK_CREATED_ID(tag)                  \
345   "<" tag "_response"                           \
346   " status=\"" STATUS_OK_CREATED "\""           \
347   " status_text=\"" STATUS_OK_CREATED_TEXT "\"" \
348   " id=\"%s\"/>"
349 
350 /**
351  * @brief Expand to XML for a STATUS_OK_REQUESTED response.
352  *
353  * @param  tag  Name of the command generating the response.
354  */
355 #define XML_OK_REQUESTED(tag)           \
356   "<" tag "_response"                   \
357   " status=\"" STATUS_OK_REQUESTED "\"" \
358   " status_text=\"" STATUS_OK_REQUESTED_TEXT "\"/>"
359 
360 /**
361  * @brief Expand to XML for a STATUS_INTERNAL_ERROR response.
362  *
363  * @param  tag  Name of the command generating the response.
364  */
365 #define XML_INTERNAL_ERROR(tag)           \
366   "<" tag "_response"                     \
367   " status=\"" STATUS_INTERNAL_ERROR "\"" \
368   " status_text=\"" STATUS_INTERNAL_ERROR_TEXT "\"/>"
369 
370 /**
371  * @brief Sends XML for a STATUS_SERVICE_DOWN response.
372  *
373  * @param  tag  Name of the command generating the response.
374  */
375 #define SEND_XML_SERVICE_DOWN(tag)                                           \
376   do                                                                         \
377     {                                                                        \
378       char *str;                                                             \
379       str =                                                                  \
380         g_strdup_printf ("<%s_response status='%s' status_text='%s'/>", tag, \
381                          STATUS_SERVICE_DOWN, STATUS_SERVICE_DOWN_TEXT);     \
382       SEND_TO_CLIENT_OR_FAIL (str);                                          \
383       g_free (str);                                                          \
384     }                                                                        \
385   while (0);
386 
387 #endif /* not _GVMD_GMP_BASE_H */
388