Greenbone Vulnerability Management Libraries  10.0.0
osp.c
Go to the documentation of this file.
1 /* Copyright (C) 2014-2019 Greenbone Networks GmbH
2  *
3  * SPDX-License-Identifier: GPL-2.0-or-later
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the 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 General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
25 #include "osp.h"
26 
27 #include "../base/hosts.h" /* for gvm_get_host_type */
28 #include "../util/serverutils.h" /* for gvm_server_close, gvm_server_open_w... */
29 #include "../util/xmlutils.h" /* for entity_child, entity_text, free_entity */
30 
31 #include <assert.h> /* for assert */
32 #include <gnutls/gnutls.h> /* for gnutls_session_int, gnutls_session_t */
33 #include <stdarg.h> /* for va_list */
34 #include <stdlib.h> /* for NULL, atoi */
35 #include <string.h> /* for strcmp, strlen, strncpy */
36 #include <sys/socket.h> /* for AF_UNIX, connect, socket, SOCK_STREAM */
37 #include <sys/un.h> /* for sockaddr_un, sa_family_t */
38 #include <unistd.h> /* for close */
39 
40 #undef G_LOG_DOMAIN
41 
44 #define G_LOG_DOMAIN "lib osp"
45 
50 {
51  gnutls_session_t session;
52  int socket;
53  char *host;
54  int port;
55 };
56 
60 struct osp_param
61 {
62  char *id;
63  char *name;
64  char *desc;
65  char *def;
67  int mandatory;
68 };
69 
70 static int
71 osp_send_command (osp_connection_t *, entity_t *, const char *, ...)
72  __attribute__ ((__format__ (__printf__, 3, 4)));
73 
86 osp_connection_new (const char *host, int port, const char *cacert,
87  const char *cert, const char *key)
88 {
89  osp_connection_t *connection;
90 
91  if (host && *host == '/')
92  {
93  struct sockaddr_un addr;
94  int len;
95 
96  connection = g_malloc0 (sizeof (*connection));
97  connection->socket = socket (AF_UNIX, SOCK_STREAM, 0);
98  if (connection->socket == -1)
99  return NULL;
100 
101  addr.sun_family = AF_UNIX;
102  strncpy (addr.sun_path, host, sizeof (addr.sun_path) - 1);
103  len = strlen (addr.sun_path) + sizeof (addr.sun_family);
104  if (connect (connection->socket, (struct sockaddr *) &addr, len) == -1)
105  {
106  close (connection->socket);
107  return NULL;
108  }
109  }
110  else
111  {
112  if (port <= 0 || port > 65535)
113  return NULL;
114  if (!host || gvm_get_host_type (host) == -1)
115  return NULL;
116  if (!cert || !key || !cacert)
117  return NULL;
118 
119  connection = g_malloc0 (sizeof (*connection));
120  connection->socket = gvm_server_open_with_cert (
121  &connection->session, host, port, cacert, cert, key);
122  }
123  if (connection->socket == -1)
124  {
125  g_free (connection);
126  return NULL;
127  }
128 
129  connection->host = g_strdup (host);
130  connection->port = port;
131  return connection;
132 }
133 
143 int
144 osp_send_command (osp_connection_t *connection, entity_t *response,
145  const char *fmt, ...)
146 {
147  va_list ap;
148  int rc = 1;
149 
150  va_start (ap, fmt);
151 
152  if (!connection || !fmt || !response)
153  goto out;
154 
155  if (*connection->host == '/')
156  {
157  if (gvm_socket_vsendf (connection->socket, fmt, ap) == -1)
158  goto out;
159  if (read_entity_s (connection->socket, response))
160  goto out;
161  }
162  else
163  {
164  if (gvm_server_vsendf (&connection->session, fmt, ap) == -1)
165  goto out;
166  if (read_entity (&connection->session, response))
167  goto out;
168  }
169 
170  rc = 0;
171 
172 out:
173  va_end (ap);
174 
175  return rc;
176 }
177 
183 void
185 {
186  if (!connection)
187  return;
188 
189  if (*connection->host == '/')
190  close (connection->socket);
191  else
192  gvm_server_close (connection->socket, connection->session);
193  g_free (connection->host);
194  g_free (connection);
195 }
196 
210 int
211 osp_get_version (osp_connection_t *connection, char **s_name, char **s_version,
212  char **d_name, char **d_version, char **p_name,
213  char **p_version)
214 {
215  entity_t entity, child, gchild;
216 
217  if (!connection)
218  return 1;
219 
220  if (osp_send_command (connection, &entity, "<get_version/>"))
221  return 1;
222 
223  child = entity_child (entity, "scanner");
224  if (!child)
225  goto err_get_version;
226  gchild = entity_child (child, "name");
227  if (!gchild)
228  goto err_get_version;
229  if (s_name)
230  *s_name = g_strdup (entity_text (gchild));
231  gchild = entity_child (child, "version");
232  if (!gchild)
233  goto err_get_version;
234  if (s_version)
235  *s_version = g_strdup (entity_text (gchild));
236 
237  child = entity_child (entity, "daemon");
238  if (!child)
239  goto err_get_version;
240  gchild = entity_child (child, "name");
241  if (!gchild)
242  goto err_get_version;
243  if (d_name)
244  *d_name = g_strdup (entity_text (gchild));
245  gchild = entity_child (child, "version");
246  if (!gchild)
247  goto err_get_version;
248  if (d_version)
249  *d_version = g_strdup (entity_text (gchild));
250 
251  child = entity_child (entity, "protocol");
252  if (!child)
253  goto err_get_version;
254  gchild = entity_child (child, "name");
255  if (!gchild)
256  goto err_get_version;
257  if (p_name)
258  *p_name = g_strdup (entity_text (gchild));
259  gchild = entity_child (child, "version");
260  if (!gchild)
261  goto err_get_version;
262  if (p_version)
263  *p_version = g_strdup (entity_text (gchild));
264 
265  free_entity (entity);
266  return 0;
267 
268 err_get_version:
269  g_warning ("Erroneous OSP <get_version/> response.");
270  if (s_name)
271  g_free (*s_name);
272  if (s_version)
273  g_free (*s_version);
274  if (d_name)
275  g_free (*d_name);
276  if (d_version)
277  g_free (*d_version);
278  if (p_name)
279  g_free (*p_name);
280  if (p_version)
281  g_free (*p_version);
282  free_entity (entity);
283  return 1;
284 }
285 
294 int
295 osp_delete_scan (osp_connection_t *connection, const char *scan_id)
296 {
297  entity_t entity;
298  int ret = 0;
299  const char *status;
300 
301  if (!connection)
302  return 1;
303 
304  ret = osp_send_command (connection, &entity, "<delete_scan scan_id='%s'/>",
305  scan_id);
306  if (ret)
307  return 1;
308 
309  /* Check response status. */
310  status = entity_attribute (entity, "status");
311  assert (status);
312  if (strcmp (status, "200"))
313  ret = 1;
314 
315  free_entity (entity);
316  return ret;
317 }
318 
330 int
331 osp_get_scan (osp_connection_t *connection, const char *scan_id,
332  char **report_xml, int details, char **error)
333 {
334  entity_t entity, child;
335  int progress;
336  int rc;
337 
338  assert (connection);
339  assert (scan_id);
340  rc = osp_send_command (connection, &entity,
341  "<get_scans scan_id='%s' details='%d'/>", scan_id,
342  details ? 1 : 0);
343  if (rc)
344  {
345  if (error)
346  *error = g_strdup ("Couldn't send get_scans command to scanner");
347  return -1;
348  }
349 
350  child = entity_child (entity, "scan");
351  if (!child)
352  {
353  const char *text = entity_attribute (entity, "status_text");
354 
355  assert (text);
356  if (error)
357  *error = g_strdup (text);
358  free_entity (entity);
359  return -1;
360  }
361  progress = atoi (entity_attribute (child, "progress"));
362  if (report_xml)
363  {
364  GString *string;
365 
366  string = g_string_new ("");
367  print_entity_to_string (child, string);
368  *report_xml = g_string_free (string, FALSE);
369  }
370  free_entity (entity);
371  return progress;
372 }
373 
383 int
384 osp_stop_scan (osp_connection_t *connection, const char *scan_id, char **error)
385 {
386  entity_t entity;
387  int rc;
388 
389  assert (connection);
390  assert (scan_id);
391  rc = osp_send_command (connection, &entity, "<stop_scan scan_id='%s'/>",
392  scan_id);
393  if (rc)
394  {
395  if (error)
396  *error = g_strdup ("Couldn't send stop_scan command to scanner");
397  return -1;
398  }
399 
400  rc = atoi (entity_attribute (entity, "status"));
401  if (rc == 200)
402  {
403  free_entity (entity);
404  return 0;
405  }
406  else
407  {
408  const char *text = entity_attribute (entity, "status_text");
409 
410  assert (text);
411  if (error)
412  *error = g_strdup (text);
413  free_entity (entity);
414  return -1;
415  }
416 }
417 
426 static void
427 option_concat_as_xml (gpointer key, gpointer value, gpointer pstr)
428 {
429  char *options_str, *tmp, *key_escaped, *value_escaped;
430 
431  options_str = *(char **) pstr;
432 
433  key_escaped = g_markup_escape_text ((char *) key, -1);
434  value_escaped = g_markup_escape_text ((char *) value, -1);
435  tmp = g_strdup_printf ("%s<%s>%s</%s>", options_str ? options_str : "",
436  key_escaped, value_escaped, key_escaped);
437 
438  g_free (options_str);
439  g_free (key_escaped);
440  g_free (value_escaped);
441  *(char **) pstr = tmp;
442 }
443 
456 int
457 osp_start_scan (osp_connection_t *connection, const char *target,
458  const char *ports, GHashTable *options, const char *scan_id,
459  char **error)
460 {
461  entity_t entity;
462  char *options_str = NULL;
463  int status;
464  int rc;
465 
466  assert (connection);
467  assert (target);
468  /* Construct options string. */
469  if (options)
470  g_hash_table_foreach (options, option_concat_as_xml, &options_str);
471 
472  rc = osp_send_command (connection, &entity,
473  "<start_scan target='%s' ports='%s' scan_id='%s'>"
474  "<scanner_params>%s</scanner_params></start_scan>",
475  target, ports ? ports : "", scan_id ? scan_id : "",
476  options_str ? options_str : "");
477  g_free (options_str);
478  if (rc)
479  {
480  if (error)
481  *error = g_strdup ("Couldn't send start_scan command to scanner");
482  return -1;
483  }
484 
485  status = atoi (entity_attribute (entity, "status"));
486  if (status == 200)
487  {
488  free_entity (entity);
489  return 0;
490  }
491  else
492  {
493  const char *text = entity_attribute (entity, "status_text");
494 
495  assert (text);
496  if (error)
497  *error = g_strdup (text);
498  free_entity (entity);
499  return -1;
500  }
501 }
502 
510 static osp_param_type_t
511 osp_param_str_to_type (const char *str)
512 {
513  assert (str);
514  if (!strcmp (str, "integer"))
515  return OSP_PARAM_TYPE_INT;
516  else if (!strcmp (str, "string"))
517  return OSP_PARAM_TYPE_STR;
518  else if (!strcmp (str, "password"))
520  else if (!strcmp (str, "file"))
521  return OSP_PARAM_TYPE_FILE;
522  else if (!strcmp (str, "boolean"))
523  return OSP_PARAM_TYPE_BOOLEAN;
524  else if (!strcmp (str, "ovaldef_file"))
526  else if (!strcmp (str, "selection"))
528  else if (!strcmp (str, "credential_up"))
529  return OSP_PARAM_TYPE_CRD_UP;
530  assert (0);
531  return 0;
532 }
533 
541 const char *
543 {
544  osp_param_type_t type;
545 
546  assert (param);
547  type = param->type;
548  if (type == OSP_PARAM_TYPE_INT)
549  return "integer";
550  else if (type == OSP_PARAM_TYPE_STR)
551  return "string";
552  else if (type == OSP_PARAM_TYPE_PASSWORD)
553  return "password";
554  else if (type == OSP_PARAM_TYPE_FILE)
555  return "file";
556  else if (type == OSP_PARAM_TYPE_BOOLEAN)
557  return "boolean";
558  else if (type == OSP_PARAM_TYPE_OVALDEF_FILE)
559  return "ovaldef_file";
560  else if (type == OSP_PARAM_TYPE_SELECTION)
561  return "selection";
562  else if (type == OSP_PARAM_TYPE_CRD_UP)
563  return "credential_up";
564  assert (0);
565  return NULL;
566 }
567 
577 int
578 osp_get_scanner_details (osp_connection_t *connection, char **desc,
579  GSList **params)
580 {
581  entity_t entity, child;
582  entities_t entities;
583 
584  assert (connection);
585 
586  if (osp_send_command (connection, &entity, "<get_scanner_details/>"))
587  return 1;
588  if (params)
589  {
590  child = entity_child (entity, "scanner_params");
591  if (!child)
592  {
593  free_entity (entity);
594  return 1;
595  }
596  entities = child->entities;
597  while (entities)
598  {
599  osp_param_t *param;
600 
601  child = entities->data;
602  param = osp_param_new ();
603  param->id = g_strdup (entity_attribute (child, "id"));
604  param->type =
605  osp_param_str_to_type (entity_attribute (child, "type"));
606  param->name = g_strdup (entity_text (entity_child (child, "name")));
607  param->desc =
608  g_strdup (entity_text (entity_child (child, "description")));
609  param->def = g_strdup (entity_text (entity_child (child, "default")));
610  if (entity_child (child, "mandatory"))
611  param->mandatory =
612  atoi (entity_text (entity_child (child, "mandatory")));
613  *params = g_slist_append (*params, param);
614  entities = next_entities (entities);
615  }
616  }
617  if (desc)
618  {
619  child = entity_child (entity, "description");
620  assert (child);
621  *desc = g_strdup (entity_text (child));
622  }
623 
624  free_entity (entity);
625  return 0;
626 }
627 
633 osp_param_t *
635 {
636  return g_malloc0 (sizeof (osp_param_t));
637 }
638 
646 const char *
647 osp_param_id (const osp_param_t *param)
648 {
649  assert (param);
650 
651  return param->id;
652 }
653 
661 const char *
663 {
664  assert (param);
665 
666  return param->name;
667 }
668 
676 const char *
678 {
679  assert (param);
680 
681  return param->desc;
682 }
683 
691 const char *
693 {
694  assert (param);
695 
696  return param->def;
697 }
698 
706 int
708 {
709  assert (param);
710 
711  return param->mandatory;
712 }
713 
719 void
721 {
722  if (!param)
723  return;
724  g_free (param->id);
725  g_free (param->name);
726  g_free (param->desc);
727  g_free (param->def);
728  g_free (param);
729 }
Struct holding options for OSP parameters.
Definition: osp.c:60
char * desc
Definition: osp.c:64
Struct holding options for OSP connection.
Definition: osp.c:49
void osp_param_free(osp_param_t *param)
Free an OSP parameter.
Definition: osp.c:720
osp_param_t * osp_param_new(void)
Create a new OSP parameter.
Definition: osp.c:634
osp_param_type_t
OSP parameter types.
Definition: osp.h:35
int osp_get_scanner_details(osp_connection_t *connection, char **desc, GSList **params)
Get an OSP scanner's details.
Definition: osp.c:578
const char * osp_param_type_str(const osp_param_t *param)
Get an OSP parameter in string format form its type.
Definition: osp.c:542
int gvm_get_host_type(const gchar *str_stripped)
Determines the host type in a buffer.
Definition: hosts.c:768
API for Open Scanner Protocol communication.
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: xmlutils.c:1197
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)
Get the scanner version from an OSP server.
Definition: osp.c:211
static int osp_send_command(osp_connection_t *, entity_t *, const char *,...)
Send a command to an OSP server.
Definition: osp.c:71
int socket
Definition: osp.c:52
XML element.
Definition: xmlutils.h:65
static void option_concat_as_xml(gpointer key, gpointer value, gpointer pstr)
Concatenate options as xml.
Definition: osp.c:427
int gvm_socket_vsendf(int socket, const char *fmt, va_list ap)
Send a string to the server.
Definition: serverutils.c:758
entities_t entities
Children.
Definition: xmlutils.h:70
int read_entity(gnutls_session_t *session, entity_t *entity)
Read an XML entity tree from the manager.
Definition: xmlutils.c:1057
entity_t entity_child(entity_t entity, const char *name)
Get a child of an entity.
Definition: xmlutils.c:205
char * name
Definition: osp.c:63
const char * osp_param_name(const osp_param_t *param)
Get an OSP parameter's name.
Definition: osp.c:662
const char * osp_param_desc(const osp_param_t *param)
Get an OSP parameter's description.
Definition: osp.c:677
static osp_param_type_t osp_param_str_to_type(const char *str)
Get an OSP parameter's type from its string format.
Definition: osp.c:511
const char * entity_attribute(entity_t entity, const char *name)
Get an attribute of an entity.
Definition: xmlutils.c:228
osp_param_type_t type
Definition: osp.c:66
int osp_stop_scan(osp_connection_t *connection, const char *scan_id, char **error)
Stop a scan on an OSP server.
Definition: osp.c:384
int osp_delete_scan(osp_connection_t *connection, const char *scan_id)
Delete a scan from an OSP server.
Definition: osp.c:295
int osp_param_mandatory(const osp_param_t *param)
Get an OSP parameter's mandatory value.
Definition: osp.c:707
int port
Definition: osp.c:54
int read_entity_s(int socket, entity_t *entity)
Read an XML entity tree from the socket.
Definition: xmlutils.c:1071
int osp_start_scan(osp_connection_t *connection, const char *target, const char *ports, GHashTable *options, const char *scan_id, char **error)
Start an OSP scan against a target.
Definition: osp.c:457
void osp_connection_close(osp_connection_t *connection)
Close a connection to an OSP server.
Definition: osp.c:184
char * def
Definition: osp.c:65
int osp_get_scan(osp_connection_t *connection, const char *scan_id, char **report_xml, int details, char **error)
Get a scan from an OSP server.
Definition: osp.c:331
char * entity_text(entity_t entity)
Get the text an entity.
Definition: xmlutils.c:157
const char * osp_param_id(const osp_param_t *param)
Get an OSP parameter's id.
Definition: osp.c:647
int gvm_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.
Definition: serverutils.c:475
int gvm_server_close(int socket, gnutls_session_t session)
Close a server connection and its socket.
Definition: serverutils.c:507
int gvm_server_vsendf(gnutls_session_t *session, const char *fmt, va_list ap)
Send a string to the server.
Definition: serverutils.c:743
gnutls_session_t session
Definition: osp.c:51
int mandatory
Definition: osp.c:67
void free_entity(entity_t entity)
Free an entity, recursively.
Definition: xmlutils.c:127
char * id
Definition: osp.c:62
const char * osp_param_default(const osp_param_t *param)
Get an OSP parameter's default value.
Definition: osp.c:692
GSList * entities_t
Entities.
Definition: xmlutils.h:60
char * host
Definition: osp.c:53
entities_t next_entities(entities_t entities)
Return all the entities from an entities_t after the first.
Definition: xmlutils.c:79
osp_connection_t * osp_connection_new(const char *, int, const char *, const char *, const char *)