OpenVAS Libraries  9.0.3
osp.c
Go to the documentation of this file.
1 /* openvas-libraries/osp
2  * $Id$
3  * Description: API to handle OSP implementation.
4  *
5  * Authors:
6  * Hani Benhabiles <hani.benhabiles@greenbone.net>
7  *
8  * Copyright:
9  * Copyright (C) 2014 Greenbone Networks GmbH
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 
26 #include <glib.h>
27 
28 #include "../base/openvas_hosts.h"
29 #include "../misc/openvas_server.h"
30 #include "../omp/xml.h"
31 #include "osp.h"
32 
33 
34 #undef G_LOG_DOMAIN
35 #define G_LOG_DOMAIN "lib osp"
36 
38  gnutls_session_t session;
39  int socket;
40  char *host;
41  int port;
42 };
43 
44 struct osp_param {
45  char *id;
46  char *name;
47  char *desc;
48  char *def;
50  int mandatory;
51 };
52 
53 static int
54 osp_send_command (osp_connection_t *, entity_t *, const char *, ...)
55  __attribute__((__format__(__printf__, 3, 4)));
56 
57 
58 /* @brief Open a new connection to an OSP server.
59  *
60  * @param[in] host Host of OSP server.
61  * @param[in] port Port of OSP server.
62  * @param[in] cacert CA public key.
63  * @param[in] cert Client public key.
64  * @param[in] key Client private key.
65  *
66  * @return New osp connection, NULL if error.
67  */
69 osp_connection_new (const char *host, int port, const char *cacert,
70  const char *cert, const char *key)
71 {
72  osp_connection_t *connection;
73 
74  if (port <= 0 || port > 65535)
75  return NULL;
76  if (!host || openvas_get_host_type (host) == -1)
77  return NULL;
78  if (!cert || !key || !cacert)
79  return NULL;
80 
81  connection = g_malloc0(sizeof (*connection));
83  (&connection->session, host, port, cacert, cert, key);
84  if (connection->socket == -1)
85  {
86  g_free (connection);
87  return NULL;
88  }
89 
90  connection->host = g_strdup (host);
91  connection->port = port;
92  return connection;
93 }
94 
95 /* @brief Send a command to an OSP server.
96  *
97  * @param[in] connection Connection to OSP server.
98  * @param[in] command OSP Command to send.
99  * @param[out] response Response from OSP server.
100  *
101  * @return 0 and response, 1 if error.
102  */
103 int
104 osp_send_command (osp_connection_t *connection, entity_t *response,
105  const char *fmt, ...)
106 {
107  va_list ap;
108  int rc = 1;
109 
110  va_start (ap, fmt);
111 
112  if (!connection || !fmt || !response)
113  goto out;
114 
115  if (openvas_server_vsendf (&connection->session, fmt, ap) == -1)
116  goto out;
117 
118  if (read_entity (&connection->session, response))
119  goto out;
120 
121  rc = 0;
122 
123 out:
124  va_end(ap);
125 
126  return rc;
127 }
128 
129 /* @brief Close a connection to an OSP server.
130  *
131  * @param[in] connection Connection to OSP server to close.
132  */
133 void
135 {
136  if (!connection)
137  return;
138 
139  openvas_server_close (connection->socket, connection->session);
140  g_free (connection->host);
141  g_free (connection);
142 }
143 
144 /* @brief Get the scanner version from an OSP server.
145  *
146  * @param[in] connection Connection to an OSP server.
147  * @param[out] s_name Parsed scanner name.
148  * @param[out] s_version Parsed scanner version.
149  * @param[out] d_name Parsed scanner name.
150  * @param[out] d_version Parsed scanner version.
151  * @param[out] p_name Parsed scanner name.
152  * @param[out] p_version Parsed scanner version.
153  *
154  * @return 0 if success, 1 if error.
155  */
156 int
157 osp_get_version (osp_connection_t *connection, char **s_name, char **s_version,
158  char **d_name, char **d_version, char **p_name,
159  char **p_version)
160 {
161  entity_t entity, child, gchild;
162 
163  if (!connection)
164  return 1;
165 
166  if (osp_send_command (connection, &entity, "<get_version/>"))
167  return 1;
168 
169  child = entity_child (entity, "scanner");
170  if (!child)
171  goto err_get_version;
172  gchild = entity_child (child, "name");
173  if (!gchild)
174  goto err_get_version;
175  if (s_name)
176  *s_name = g_strdup (entity_text (gchild));
177  gchild = entity_child (child, "version");
178  if (!gchild)
179  goto err_get_version;
180  if (s_version)
181  *s_version = g_strdup (entity_text (gchild));
182 
183  child = entity_child (entity, "daemon");
184  if (!child)
185  goto err_get_version;
186  gchild = entity_child (child, "name");
187  if (!gchild)
188  goto err_get_version;
189  if (d_name)
190  *d_name = g_strdup (entity_text (gchild));
191  gchild = entity_child (child, "version");
192  if (!gchild)
193  goto err_get_version;
194  if (d_version)
195  *d_version = g_strdup (entity_text (gchild));
196 
197  child = entity_child (entity, "protocol");
198  if (!child)
199  goto err_get_version;
200  gchild = entity_child (child, "name");
201  if (!gchild)
202  goto err_get_version;
203  if (p_name)
204  *p_name = g_strdup (entity_text (gchild));
205  gchild = entity_child (child, "version");
206  if (!gchild)
207  goto err_get_version;
208  if (p_version)
209  *p_version = g_strdup (entity_text (gchild));
210 
211  free_entity (entity);
212  return 0;
213 
214 err_get_version:
215  g_warning ("Erroneous OSP <get_version/> response.");
216  if (s_name)
217  g_free (*s_name);
218  if (s_version)
219  g_free (*s_version);
220  if (d_name)
221  g_free (*d_name);
222  if (d_version)
223  g_free (*d_version);
224  if (p_name)
225  g_free (*p_name);
226  if (p_version)
227  g_free (*p_version);
228  free_entity (entity);
229  return 1;
230 }
231 
232 /* @brief Delete a scan from an OSP server.
233  *
234  * @param[in] connection Connection to an OSP server.
235  * @param[in] scan_id ID of scan to delete.
236  *
237  * @return 0 if success, 1 if error.
238  */
239 int
240 osp_delete_scan (osp_connection_t *connection, const char *scan_id)
241 {
242  entity_t entity;
243  int ret = 0;
244  const char *status;
245 
246  if (!connection)
247  return 1;
248 
249  ret = osp_send_command (connection, &entity, "<delete_scan scan_id='%s'/>",
250  scan_id);
251  if (ret)
252  return 1;
253 
254  /* Check response status. */
255  status = entity_attribute (entity, "status");
256  assert (status);
257  if (strcmp (status, "200"))
258  ret = 1;
259 
260  free_entity (entity);
261  return ret;
262 }
263 
264 /* @brief Get a scan from an OSP server.
265  *
266  * @param[in] connection Connection to an OSP server.
267  * @param[in] scan_id ID of scan to get.
268  * @param[out] report_xml Scans report.
269  * @param[in] details 0 for no scan details, 1 otherwise.
270  *
271  * @return Scan progress if success, -1 if error.
272  */
273 int
274 osp_get_scan (osp_connection_t *connection, const char *scan_id,
275  char **report_xml, int details, char **error)
276 {
277  entity_t entity, child;
278  GString *string;
279  int progress;
280  int rc;
281 
282  assert (connection);
283  assert (scan_id);
284  rc = osp_send_command
285  (connection, &entity, "<get_scans scan_id='%s' details='%d'/>",
286  scan_id, details ? 1 : 0);
287  if (rc)
288  {
289  if (error)
290  *error = g_strdup ("Couldn't send get_scans command to scanner");
291  return -1;
292  }
293 
294  child = entity_child (entity, "scan");
295  if (!child)
296  {
297  const char *text = entity_attribute (entity, "status_text");
298 
299  assert (text);
300  if (error)
301  *error = g_strdup (text);
302  free_entity (entity);
303  return -1;
304  }
305  progress = atoi (entity_attribute (child, "progress"));
306  if (report_xml)
307  {
308  string = g_string_new ("");
309  print_entity_to_string (child, string);
310  *report_xml = g_string_free (string, FALSE);
311  }
312  free_entity (entity);
313  return progress;
314 }
315 
316 /* @brief Stop a scan on an OSP server.
317  *
318  * @param[in] connection Connection to an OSP server.
319  * @param[in] scan_id ID of scan to delete.
320  *
321  * @return Scan progress if success, -1 if error.
322  */
323 int
324 osp_stop_scan (osp_connection_t *connection, const char *scan_id, char **error)
325 {
326  entity_t entity;
327  int rc;
328 
329  assert (connection);
330  assert (scan_id);
331  rc = osp_send_command
332  (connection, &entity, "<stop_scan scan_id='%s'/>", scan_id);
333  if (rc)
334  {
335  if (error)
336  *error = g_strdup ("Couldn't send stop_scan command to scanner");
337  return -1;
338  }
339 
340  rc = atoi (entity_attribute (entity, "status"));
341  if (rc == 200)
342  {
343  free_entity (entity);
344  return 0;
345  }
346  else
347  {
348  const char *text = entity_attribute (entity, "status_text");
349 
350  assert (text);
351  if (error)
352  *error = g_strdup (text);
353  free_entity (entity);
354  return -1;
355  }
356 }
357 
358 static void
359 option_concat_as_xml (gpointer key, gpointer value, gpointer pstr)
360 {
361  char *options_str, *tmp, *key_escaped, *value_escaped;
362 
363  options_str = *(char **) pstr;
364 
365  key_escaped = g_markup_escape_text ((char *) key, -1);
366  value_escaped = g_markup_escape_text ((char *) value, -1);
367  tmp = g_strdup_printf ("%s<%s>%s</%s>", options_str ?: "", key_escaped,
368  value_escaped, key_escaped);
369 
370  g_free (options_str);
371  g_free (key_escaped);
372  g_free (value_escaped);
373  *(char **) pstr = tmp;
374 }
375 
376 /* @brief Start an OSP scan against a target.
377  *
378  * @param[in] connection Connection to an OSP server.
379  * @param[in] target Target host to scan.
380  * @param[in] options Table of scan options.
381  * @param[in] scan_id uuid to set for scan, null otherwise.
382  *
383  * @return 0 on success, -1 otherwise.
384  */
385 int
386 osp_start_scan (osp_connection_t *connection, const char *target,
387  const char *ports, GHashTable *options, const char *scan_id,
388  char **error)
389 {
390  entity_t entity;
391  char *options_str = NULL;
392  int status;
393  int rc;
394 
395  assert (connection);
396  assert (target);
397  /* Construct options string. */
398  if (options)
399  g_hash_table_foreach (options, option_concat_as_xml, &options_str);
400 
401  rc = osp_send_command (connection, &entity,
402  "<start_scan target='%s' ports='%s' scan_id='%s'>"
403  "<scanner_params>%s</scanner_params></start_scan>",
404  target, ports ?: "", scan_id ?: "", options_str ?: "");
405  g_free (options_str);
406  if (rc)
407  {
408  if (error)
409  *error = g_strdup ("Couldn't send start_scan command to scanner");
410  return -1;
411  }
412 
413  status = atoi (entity_attribute (entity, "status"));
414  if (status == 200)
415  {
416  free_entity (entity);
417  return 0;
418  }
419  else
420  {
421  const char *text = entity_attribute (entity, "status_text");
422 
423  assert (text);
424  if (error)
425  *error = g_strdup (text);
426  free_entity (entity);
427  return -1;
428  }
429 }
430 
431 /* @brief Get an OSP parameter's type from its string format.
432  *
433  * @param[in] str OSP parameter in string format.
434  *
435  * @return OSP parameter type.
436  */
437 static osp_param_type_t
438 osp_param_str_to_type (const char *str)
439 {
440  assert (str);
441  if (!strcmp (str, "integer"))
442  return OSP_PARAM_TYPE_INT;
443  else if (!strcmp (str, "string"))
444  return OSP_PARAM_TYPE_STR;
445  else if (!strcmp (str, "password"))
447  else if (!strcmp (str, "file"))
448  return OSP_PARAM_TYPE_FILE;
449  else if (!strcmp (str, "boolean"))
450  return OSP_PARAM_TYPE_BOOLEAN;
451  else if (!strcmp (str, "ovaldef_file"))
453  else if (!strcmp (str, "selection"))
455  else if (!strcmp (str, "credential_up"))
456  return OSP_PARAM_TYPE_CRD_UP;
457  assert (0);
458  return 0;
459 }
460 
461 const char *
463 {
464  osp_param_type_t type;
465 
466  assert (param);
467  type = param->type;
468  if (type == OSP_PARAM_TYPE_INT)
469  return "integer";
470  else if (type == OSP_PARAM_TYPE_STR)
471  return "string";
472  else if (type == OSP_PARAM_TYPE_PASSWORD)
473  return "password";
474  else if (type == OSP_PARAM_TYPE_FILE)
475  return "file";
476  else if (type == OSP_PARAM_TYPE_BOOLEAN)
477  return "boolean";
478  else if (type == OSP_PARAM_TYPE_OVALDEF_FILE)
479  return "ovaldef_file";
480  else if (type == OSP_PARAM_TYPE_SELECTION)
481  return "selection";
482  else if (type == OSP_PARAM_TYPE_CRD_UP)
483  return "credential_up";
484  assert (0);
485  return NULL;
486 }
487 
488 /* @brief Get an OSP scanner's details.
489  *
490  * @param[in] connection Connection to an OSP server.
491  * @param[out] desc Scanner's description.
492  * @param[out] params Scanner's parameters.
493  *
494  * @return 0 if success, 1 if failure.
495  */
496 int
497 osp_get_scanner_details (osp_connection_t *connection, char **desc,
498  GSList **params)
499 {
500  entity_t entity, child;
501  entities_t entities;
502 
503  assert (connection);
504 
505  if (osp_send_command (connection, &entity, "<get_scanner_details/>"))
506  return 1;
507  if (params)
508  {
509  child = entity_child (entity, "scanner_params");
510  if (!child)
511  {
512  free_entity (entity);
513  return 1;
514  }
515  entities = child->entities;
516  while (entities)
517  {
518  osp_param_t *param;
519 
520  child = entities->data;
521  param = osp_param_new ();
522  param->id = g_strdup (entity_attribute (child, "id"));
523  param->type = osp_param_str_to_type (entity_attribute (child, "type"));
524  param->name = g_strdup (entity_text (entity_child (child, "name")));
525  param->desc = g_strdup (entity_text (entity_child (child,
526  "description")));
527  param->def = g_strdup (entity_text (entity_child (child,
528  "default")));
529  if (entity_child (child, "mandatory"))
530  param->mandatory = atoi (entity_text
531  (entity_child (child, "mandatory")));
532  *params = g_slist_append (*params, param);
533  entities = next_entities (entities);
534  }
535  }
536  if (desc)
537  {
538  child = entity_child (entity, "description");
539  assert (child);
540  *desc = g_strdup (entity_text (child));
541  }
542 
543  free_entity (entity);
544  return 0;
545 }
546 
547 /* @brief Create a new OSP parameter.
548  *
549  * @return New OSP parameter.
550  */
551 osp_param_t *
553 {
554  return g_malloc0 (sizeof (osp_param_t));
555 }
556 
557 /* @brief Get an OSP parameter's id.
558  *
559  * @param[in] param OSP parameter.
560  *
561  * @return ID of OSP parameter.
562  */
563 const char *
564 osp_param_id (const osp_param_t *param)
565 {
566  assert (param);
567 
568  return param->id;
569 }
570 
571 /* @brief Get an OSP parameter's name.
572  *
573  * @param[in] param OSP parameter.
574  *
575  * @return Name of OSP parameter.
576  */
577 const char *
579 {
580  assert (param);
581 
582  return param->name;
583 }
584 
585 /* @brief Get an OSP parameter's description.
586  *
587  * @param[in] param OSP parameter.
588  *
589  * @return Description of OSP parameter.
590  */
591 const char *
593 {
594  assert (param);
595 
596  return param->desc;
597 }
598 
599 /* @brief Get an OSP parameter's default value.
600  *
601  * @param[in] param OSP parameter.
602  *
603  * @return Default value of OSP parameter.
604  */
605 const char *
607 {
608  assert (param);
609 
610  return param->def;
611 }
612 
613 /* @brief Get an OSP parameter's mandatory value.
614  *
615  * @param[in] param OSP parameter.
616  *
617  * @return Mandatory value of OSP parameter.
618  */
619 int
621 {
622  assert (param);
623 
624  return param->mandatory;
625 }
626 
627 /* @brief Free an OSP parameter.
628  *
629  * @param[in] param OSP parameter to destroy.
630  */
631 void
633 {
634  if (!param)
635  return;
636  g_free (param->id);
637  g_free (param->name);
638  g_free (param->desc);
639  g_free (param->def);
640  g_free (param);
641 }
Definition: osp.c:44
char * desc
Definition: osp.c:47
void osp_param_free(osp_param_t *param)
Definition: osp.c:632
osp_param_t * osp_param_new(void)
Definition: osp.c:552
int read_entity(gnutls_session_t *session, entity_t *entity)
Read an XML entity tree from the manager.
Definition: xml.c:1004
osp_param_type_t
Definition: osp.h:32
int osp_get_scanner_details(osp_connection_t *connection, char **desc, GSList **params)
Definition: osp.c:497
const char * osp_param_type_str(const osp_param_t *param)
Definition: osp.c:462
char * entity_text(entity_t entity)
Get the text an entity.
Definition: xml.c:178
int osp_get_version(osp_connection_t *connection, char **s_name, char **s_version, char **d_name, char **d_version, char **p_name, char **p_version)
Definition: osp.c:157
int socket
Definition: osp.c:39
XML element.
Definition: xml.h:48
entities_t entities
Children.
Definition: xml.h:53
int openvas_server_vsendf(gnutls_session_t *session, const char *fmt, va_list ap)
Send a string to the server.
char * name
Definition: osp.c:46
const char * osp_param_name(const osp_param_t *param)
Definition: osp.c:578
const char * osp_param_desc(const osp_param_t *param)
Definition: osp.c:592
const char * entity_attribute(entity_t entity, const char *name)
Get an attribute of an entity.
Definition: xml.c:241
entities_t next_entities(entities_t entities)
Return all the entities from an entities_t after the first.
Definition: xml.c:100
int openvas_server_close(int socket, gnutls_session_t session)
Close a server connection and its socket.
void print_entity_to_string(entity_t entity, GString *string)
Print an XML entity tree to a GString, appending it if string is not.
Definition: xml.c:1130
osp_param_type_t type
Definition: osp.c:49
int osp_stop_scan(osp_connection_t *connection, const char *scan_id, char **error)
Definition: osp.c:324
int osp_delete_scan(osp_connection_t *connection, const char *scan_id)
Definition: osp.c:240
int osp_param_mandatory(const osp_param_t *param)
Definition: osp.c:620
int port
Definition: osp.c:41
int osp_start_scan(osp_connection_t *connection, const char *target, const char *ports, GHashTable *options, const char *scan_id, char **error)
Definition: osp.c:386
void osp_connection_close(osp_connection_t *connection)
Definition: osp.c:134
char * def
Definition: osp.c:48
GSList * entities_t
Definition: xml.h:43
int osp_get_scan(osp_connection_t *connection, const char *scan_id, char **report_xml, int details, char **error)
Definition: osp.c:274
gchar * string
const char * osp_param_id(const osp_param_t *param)
Definition: osp.c:564
entity_t entity_child(entity_t entity, const char *name)
Get a child of an entity.
Definition: xml.c:220
int openvas_get_host_type(const gchar *str_stripped)
Determines the host type in a buffer.
int openvas_server_open_with_cert(gnutls_session_t *session, const char *host, int port, const char *ca_mem, const char *pub_mem, const char *priv_mem)
Connect to the server using a given host, port and cert.
gnutls_session_t session
Definition: osp.c:38
void free_entity(entity_t entity)
Free an entity, recursively.
Definition: xml.c:148
int mandatory
Definition: osp.c:50
char * id
Definition: osp.c:45
const char * osp_param_default(const osp_param_t *param)
Definition: osp.c:606
char * host
Definition: osp.c:40
osp_connection_t * osp_connection_new(const char *, int, const char *, const char *, const char *)