"Fossies" - the Fresh Open Source Software Archive

Member "gvm-libs-11.0.1/gmp/gmp.c" (12 May 2020, 55237 Bytes) of package /linux/misc/openvas/gvm-libs-11.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "gmp.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 11.0.0_vs_11.0.1.

    1 /* Copyright (C) 2009-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 
   20 /**
   21  * @file
   22  * @brief API for Greenbone Management Protocol communication.
   23  *
   24  * This provides higher level, GMP-aware, facilities for working with with
   25  * the Greenbone Vulnerability Manager.
   26  *
   27  * There are examples of using this interface in the gvm tests.
   28  */
   29 
   30 #include "gmp.h"
   31 
   32 #include "../util/serverutils.h" /* for gvm_server_sendf, gvm_server_sendf_xml */
   33 
   34 #include <errno.h>  /* for ERANGE, errno */
   35 #include <stdlib.h> /* for NULL, strtol, atoi */
   36 #include <string.h> /* for strlen, strdup */
   37 
   38 #undef G_LOG_DOMAIN
   39 /**
   40  * @brief GLib log domain.
   41  */
   42 #define G_LOG_DOMAIN "lib   gmp"
   43 
   44 #define GMP_FMT_BOOL_ATTRIB(var, attrib) \
   45   (var.attrib == 0 ? " " #attrib "=\"0\"" : " " #attrib "=\"1\"")
   46 
   47 #define GMP_FMT_STRING_ATTRIB(var, attrib)                                \
   48   (var.attrib ? " " #attrib "= \"" : ""), (var.attrib ? var.attrib : ""), \
   49     (var.attrib ? "\"" : "")
   50 
   51 /* GMP. */
   52 
   53 /**
   54  * @brief Get the task status from a GMP GET_TASKS response.
   55  *
   56  * @param[in]  response   GET_TASKS response.
   57  *
   58  * @return The entity_text of the status entity if the entity is found, else
   59  *         NULL.
   60  */
   61 const char *
   62 gmp_task_status (entity_t response)
   63 {
   64   entity_t task = entity_child (response, "task");
   65   if (task)
   66     {
   67       entity_t status = entity_child (task, "status");
   68       if (status)
   69         return entity_text (status);
   70     }
   71   return NULL;
   72 }
   73 
   74 /**
   75  * @brief Read response and convert status of response to a return value.
   76  *
   77  * @param[in]  session  Pointer to GNUTLS session.
   78  * @param[in]  entity   Entity containing response.
   79  *
   80  * @return 0 on success, -1 or GMP response code on error.
   81  */
   82 int
   83 gmp_check_response (gnutls_session_t *session, entity_t *entity)
   84 {
   85   int ret;
   86   const char *status;
   87 
   88   /* Read the response. */
   89 
   90   *entity = NULL;
   91   if (read_entity (session, entity))
   92     return -1;
   93 
   94   /* Check the response. */
   95 
   96   status = entity_attribute (*entity, "status");
   97   if (status == NULL)
   98     {
   99       free_entity (*entity);
  100       return -1;
  101     }
  102   if (strlen (status) == 0)
  103     {
  104       free_entity (*entity);
  105       return -1;
  106     }
  107   if (status[0] == '2')
  108     {
  109       return 0;
  110     }
  111   ret = (int) strtol (status, NULL, 10);
  112   free_entity (*entity);
  113   if (errno == ERANGE)
  114     return -1;
  115   return ret;
  116 }
  117 
  118 /**
  119  * @brief "Ping" the manager.
  120  *
  121  * @param[in]  session   Pointer to GNUTLS session.
  122  * @param[in]  timeout   Server idle time before giving up, in milliseconds.  0
  123  *                       to wait forever.
  124  *
  125  * @return 0 on success, 1 if manager closed connection, 2 on timeout,
  126  *         -1 on error.
  127  */
  128 int
  129 gmp_ping (gnutls_session_t *session, int timeout)
  130 {
  131   entity_t entity;
  132   const char *status;
  133   char first;
  134   int ret;
  135 
  136   /* Send a GET_VERSION request. */
  137 
  138   ret = gvm_server_sendf (session, "<get_version/>");
  139   if (ret)
  140     return ret;
  141 
  142   /* Read the response, with a timeout. */
  143 
  144   entity = NULL;
  145   switch (try_read_entity (session, timeout, &entity))
  146     {
  147     case 0:
  148       break;
  149     case -4:
  150       return 2;
  151     default:
  152       return -1;
  153     }
  154 
  155   /* Check the response. */
  156 
  157   status = entity_attribute (entity, "status");
  158   if (status == NULL)
  159     {
  160       free_entity (entity);
  161       return -1;
  162     }
  163   if (strlen (status) == 0)
  164     {
  165       free_entity (entity);
  166       return -1;
  167     }
  168   first = status[0];
  169   free_entity (entity);
  170   if (first == '2')
  171     return 0;
  172   return -1;
  173 }
  174 
  175 /**
  176  * @brief "Ping" the manager.
  177  *
  178  * @param[in]  connection  Pointer to GNUTLS session.
  179  * @param[in]  timeout  Server idle time before giving up, in milliseconds.  0
  180  *                      to wait forever.
  181  * @param[out] version  Return location for freshly allocated version if
  182  *                      required, else NULL.
  183  *
  184  * @return 0 on success, 1 if manager closed connection, 2 on timeout,
  185  *         -1 on error.
  186  */
  187 int
  188 gmp_ping_c (gvm_connection_t *connection, int timeout, gchar **version)
  189 {
  190   entity_t entity;
  191   const char *status;
  192   int ret;
  193 
  194   if (version && *version)
  195     *version = NULL;
  196 
  197   /* Send a GET_VERSION request. */
  198 
  199   ret = gvm_connection_sendf (connection, "<get_version/>");
  200   if (ret)
  201     return ret;
  202 
  203   /* Read the response, with a timeout. */
  204 
  205   entity = NULL;
  206   switch (try_read_entity_c (connection, timeout, &entity))
  207     {
  208     case 0:
  209       break;
  210     case -4:
  211       return 2;
  212     default:
  213       return -1;
  214     }
  215 
  216   /* Check the response. */
  217 
  218   status = entity_attribute (entity, "status");
  219   if (status == NULL)
  220     {
  221       free_entity (entity);
  222       return -1;
  223     }
  224   if (strlen (status) == 0)
  225     {
  226       free_entity (entity);
  227       return -1;
  228     }
  229   if (status[0] == '2')
  230     {
  231       if (version)
  232         {
  233           entity_t omp_version;
  234           omp_version = entity_child (entity, "version");
  235           if (omp_version == NULL)
  236             {
  237               free_entity (entity);
  238               return -1;
  239             }
  240           *version = strdup (entity_text (omp_version));
  241         }
  242       free_entity (entity);
  243       return 0;
  244     }
  245   free_entity (entity);
  246   return -1;
  247 }
  248 
  249 /**
  250  * @brief Authenticate with the manager.
  251  *
  252  * @param[in]  session   Pointer to GNUTLS session.
  253  * @param[in]  username  Username.
  254  * @param[in]  password  Password.
  255  *
  256  * @return 0 on success, 1 if manager closed connection, 2 if auth failed,
  257  *         -1 on error.
  258  */
  259 int
  260 gmp_authenticate (gnutls_session_t *session, const char *username,
  261                   const char *password)
  262 {
  263   entity_t entity;
  264   int ret;
  265 
  266   /* Send the auth request. */
  267   ret = gvm_server_sendf_xml_quiet (session,
  268                                     "<authenticate><credentials>"
  269                                     "<username>%s</username>"
  270                                     "<password>%s</password>"
  271                                     "</credentials></authenticate>",
  272                                     username ? username : "",
  273                                     password ? password : "");
  274   if (ret)
  275     return ret;
  276 
  277   /* Read the response. */
  278 
  279   entity = NULL;
  280   ret = gmp_check_response (session, &entity);
  281   if (ret == 0)
  282     {
  283       free_entity (entity);
  284       return ret;
  285     }
  286   else if (ret == -1)
  287     return ret;
  288   return 2;
  289 }
  290 
  291 /**
  292  * @brief Authenticate with the manager.
  293  *
  294  * @param[in]  session    Pointer to GNUTLS session.
  295  * @param[in]  opts       Struct containing the options to apply.
  296  * @param[out] opts       Additional account information if authentication
  297  *                        was successful.
  298  *
  299  * @return 0 on success, 1 if manager closed connection, 2 if auth failed,
  300  *         3 on timeout, -1 on error.
  301  */
  302 int
  303 gmp_authenticate_info_ext (gnutls_session_t *session,
  304                            gmp_authenticate_info_opts_t opts)
  305 {
  306   entity_t entity;
  307   const char *status;
  308   char first;
  309   int ret;
  310 
  311   *(opts.timezone) = NULL;
  312 
  313   /* Send the auth request. */
  314 
  315   ret = gvm_server_sendf_xml_quiet (session,
  316                                     "<authenticate><credentials>"
  317                                     "<username>%s</username>"
  318                                     "<password>%s</password>"
  319                                     "</credentials></authenticate>",
  320                                     opts.username, opts.password);
  321   if (ret)
  322     return ret;
  323 
  324   /* Read the response. */
  325 
  326   entity = NULL;
  327   switch (try_read_entity (session, opts.timeout, &entity))
  328     {
  329     case 0:
  330       break;
  331     case -4:
  332       return 3;
  333     default:
  334       return -1;
  335     }
  336 
  337   /* Check the response. */
  338 
  339   status = entity_attribute (entity, "status");
  340   if (status == NULL)
  341     {
  342       free_entity (entity);
  343       return -1;
  344     }
  345   if (strlen (status) == 0)
  346     {
  347       free_entity (entity);
  348       return -1;
  349     }
  350   first = status[0];
  351   if (first == '2')
  352     {
  353       entity_t timezone_entity, role_entity, severity_entity, pw_warn_entity;
  354       /* Get the extra info. */
  355       timezone_entity = entity_child (entity, "timezone");
  356       if (timezone_entity)
  357         *opts.timezone = g_strdup (entity_text (timezone_entity));
  358       role_entity = entity_child (entity, "role");
  359       if (role_entity)
  360         *opts.role = g_strdup (entity_text (role_entity));
  361       severity_entity = entity_child (entity, "severity");
  362       if (severity_entity)
  363         *opts.severity = g_strdup (entity_text (severity_entity));
  364       pw_warn_entity = entity_child (entity, "password_warning");
  365       if (pw_warn_entity)
  366         *(opts.pw_warning) = g_strdup (entity_text (pw_warn_entity));
  367       else
  368         *(opts.pw_warning) = NULL;
  369 
  370       free_entity (entity);
  371       return 0;
  372     }
  373   free_entity (entity);
  374   return 2;
  375 }
  376 
  377 /**
  378  * @brief Authenticate with the manager.
  379  *
  380  * @param[in]  connection  Connection
  381  * @param[in]  opts        Struct containing the options to apply.
  382  *
  383  * @return 0 on success, 1 if manager closed connection, 2 if auth failed,
  384  *         3 on timeout, -1 on error.
  385  */
  386 int
  387 gmp_authenticate_info_ext_c (gvm_connection_t *connection,
  388                              gmp_authenticate_info_opts_t opts)
  389 {
  390   entity_t entity;
  391   const char *status;
  392   char first;
  393   int ret;
  394 
  395   if (opts.timezone)
  396     *(opts.timezone) = NULL;
  397 
  398   /* Send the auth request. */
  399 
  400   ret = gvm_connection_sendf_xml_quiet (connection,
  401                                         "<authenticate>"
  402                                         "<credentials>"
  403                                         "<username>%s</username>"
  404                                         "<password>%s</password>"
  405                                         "</credentials>"
  406                                         "</authenticate>",
  407                                         opts.username, opts.password);
  408   if (ret)
  409     return ret;
  410 
  411   /* Read the response. */
  412 
  413   entity = NULL;
  414   switch (try_read_entity_c (connection, opts.timeout, &entity))
  415     {
  416     case 0:
  417       break;
  418     case -4:
  419       return 3;
  420     default:
  421       return -1;
  422     }
  423 
  424   /* Check the response. */
  425 
  426   status = entity_attribute (entity, "status");
  427   if (status == NULL)
  428     {
  429       free_entity (entity);
  430       return -1;
  431     }
  432   if (strlen (status) == 0)
  433     {
  434       free_entity (entity);
  435       return -1;
  436     }
  437   first = status[0];
  438   if (first == '2')
  439     {
  440       entity_t timezone_entity, role_entity, severity_entity;
  441       /* Get the extra info. */
  442       timezone_entity = entity_child (entity, "timezone");
  443       if (timezone_entity && opts.timezone)
  444         *opts.timezone = g_strdup (entity_text (timezone_entity));
  445       role_entity = entity_child (entity, "role");
  446       if (role_entity && opts.role)
  447         *opts.role = g_strdup (entity_text (role_entity));
  448       severity_entity = entity_child (entity, "severity");
  449       if (severity_entity && opts.severity)
  450         *opts.severity = g_strdup (entity_text (severity_entity));
  451       if (opts.pw_warning)
  452         {
  453           entity_t pw_warn_entity;
  454           pw_warn_entity = entity_child (entity, "password_warning");
  455           if (pw_warn_entity)
  456             *(opts.pw_warning) = g_strdup (entity_text (pw_warn_entity));
  457           else
  458             *(opts.pw_warning) = NULL;
  459         }
  460 
  461       free_entity (entity);
  462       return 0;
  463     }
  464   free_entity (entity);
  465   return 2;
  466 }
  467 
  468 /**
  469  * @brief Create a task.
  470  *
  471  * FIXME: Using the according opts it should be possible to generate
  472  * any type of create_task request defined by the spec.
  473  *
  474  * @param[in]  session   Pointer to GNUTLS session.
  475  * @param[in]  opts      Struct containing the options to apply.
  476  * @param[out]  id       Pointer for newly allocated ID of new task, or NULL.
  477  *                       Only set on successful return.
  478  *
  479  * @return 0 on success, -1 or GMP response code on error.
  480  */
  481 int
  482 gmp_create_task_ext (gnutls_session_t *session, gmp_create_task_opts_t opts,
  483                      gchar **id)
  484 {
  485   /* Create the GMP request. */
  486 
  487   gchar *prefs, *start, *hosts_ordering, *scanner, *schedule, *slave;
  488   GString *alerts, *observers;
  489   int ret;
  490   if ((opts.config_id == NULL) || (opts.target_id == NULL))
  491     return -1;
  492 
  493   prefs = NULL;
  494   start = g_markup_printf_escaped (
  495     "<create_task>"
  496     "<config id=\"%s\"/>"
  497     "<target id=\"%s\"/>"
  498     "<name>%s</name>"
  499     "<comment>%s</comment>"
  500     "<alterable>%d</alterable>",
  501     opts.config_id, opts.target_id, opts.name ? opts.name : "unnamed",
  502     opts.comment ? opts.comment : "", opts.alterable ? 1 : 0);
  503 
  504   if (opts.hosts_ordering)
  505     hosts_ordering = g_strdup_printf ("<hosts_ordering>%s</hosts_ordering>",
  506                                       opts.hosts_ordering);
  507   else
  508     hosts_ordering = NULL;
  509 
  510   if (opts.scanner_id)
  511     scanner = g_strdup_printf ("<scanner id=\"%s\"/>", opts.scanner_id);
  512   else
  513     scanner = NULL;
  514 
  515   if (opts.schedule_id)
  516     schedule = g_strdup_printf ("<schedule id=\"%s\"/>"
  517                                 "<schedule_periods>%d</schedule_periods>",
  518                                 opts.schedule_id, opts.schedule_periods);
  519   else
  520     schedule = NULL;
  521 
  522   if (opts.slave_id)
  523     slave = g_strdup_printf ("<slave id=\"%s\"/>", opts.slave_id);
  524   else
  525     slave = NULL;
  526 
  527   if (opts.max_checks || opts.max_hosts || opts.in_assets || opts.source_iface)
  528     {
  529       gchar *in_assets, *checks, *hosts, *source_iface;
  530 
  531       in_assets = checks = hosts = source_iface = NULL;
  532 
  533       if (opts.in_assets)
  534         in_assets = g_markup_printf_escaped ("<preference>"
  535                                              "<scanner_name>"
  536                                              "in_assets"
  537                                              "</scanner_name>"
  538                                              "<value>"
  539                                              "%s"
  540                                              "</value>"
  541                                              "</preference>",
  542                                              opts.in_assets);
  543 
  544       if (opts.max_hosts)
  545         hosts = g_markup_printf_escaped ("<preference>"
  546                                          "<scanner_name>"
  547                                          "max_hosts"
  548                                          "</scanner_name>"
  549                                          "<value>"
  550                                          "%s"
  551                                          "</value>"
  552                                          "</preference>",
  553                                          opts.max_hosts);
  554 
  555       if (opts.max_checks)
  556         checks = g_markup_printf_escaped ("<preference>"
  557                                           "<scanner_name>"
  558                                           "max_checks"
  559                                           "</scanner_name>"
  560                                           "<value>"
  561                                           "%s"
  562                                           "</value>"
  563                                           "</preference>",
  564                                           opts.max_checks);
  565 
  566       if (opts.source_iface)
  567         source_iface = g_markup_printf_escaped ("<preference>"
  568                                                 "<scanner_name>"
  569                                                 "source_iface"
  570                                                 "</scanner_name>"
  571                                                 "<value>"
  572                                                 "%s"
  573                                                 "</value>"
  574                                                 "</preference>",
  575                                                 opts.source_iface);
  576 
  577       prefs =
  578         g_strdup_printf ("<preferences>%s%s%s%s</preferences>",
  579                          in_assets ? in_assets : "", checks ? checks : "",
  580                          hosts ? hosts : "", source_iface ? source_iface : "");
  581       g_free (in_assets);
  582       g_free (checks);
  583       g_free (hosts);
  584       g_free (source_iface);
  585     }
  586 
  587   if (opts.alert_ids)
  588     {
  589       unsigned int i;
  590       alerts = g_string_new ("");
  591       for (i = 0; i < opts.alert_ids->len; i++)
  592         {
  593           char *alert = (char *) g_ptr_array_index (opts.alert_ids, i);
  594           g_string_append_printf (alerts, "<alert id=\"%s\"/>", alert);
  595         }
  596     }
  597   else
  598     alerts = g_string_new ("");
  599 
  600   if (opts.observers || opts.observer_groups)
  601     {
  602       observers = g_string_new ("<observers>");
  603 
  604       if (opts.observers)
  605         g_string_append (observers, opts.observers);
  606 
  607       if (opts.observer_groups)
  608         {
  609           unsigned int i;
  610           for (i = 0; i < opts.observer_groups->len; i++)
  611             {
  612               char *group =
  613                 (char *) g_ptr_array_index (opts.observer_groups, i);
  614               g_string_append_printf (observers, "<group id=\"%s\"/>", group);
  615             }
  616         }
  617       g_string_append (observers, "</observers>");
  618     }
  619   else
  620     observers = g_string_new ("");
  621 
  622   /* Send the request. */
  623   ret = gvm_server_sendf (
  624     session, "%s%s%s%s%s%s%s%s</create_task>", start, prefs ? prefs : "",
  625     hosts_ordering ? hosts_ordering : "", scanner ? scanner : "",
  626     schedule ? schedule : "", slave ? slave : "", alerts ? alerts->str : "",
  627     observers ? observers->str : "");
  628   g_free (start);
  629   g_free (prefs);
  630   g_free (hosts_ordering);
  631   g_free (scanner);
  632   g_free (schedule);
  633   g_free (slave);
  634   g_string_free (alerts, TRUE);
  635   g_string_free (observers, TRUE);
  636 
  637   if (ret)
  638     return -1;
  639 
  640   /* Read the response. */
  641 
  642   ret = gmp_read_create_response (session, id);
  643   if (ret == 201)
  644     return 0;
  645   return ret;
  646 }
  647 
  648 /**
  649  * @brief Create a task given a config and target.
  650  *
  651  * @param[in]   session     Pointer to GNUTLS session.
  652  * @param[in]   name        Task name.
  653  * @param[in]   config      Task config name.
  654  * @param[in]   target      Task target name.
  655  * @param[in]   comment     Task comment.
  656  * @param[out]  id          Pointer for newly allocated ID of new task.  Only
  657  *                          set on successful return.
  658  *
  659  * @return 0 on success, -1 or GMP response code on error.
  660  */
  661 int
  662 gmp_create_task (gnutls_session_t *session, const char *name,
  663                  const char *config, const char *target, const char *comment,
  664                  gchar **id)
  665 {
  666   int ret;
  667 
  668   ret = gvm_server_sendf_xml (session,
  669                               "<create_task>"
  670                               "<config id=\"%s\"/>"
  671                               "<target id=\"%s\"/>"
  672                               "<name>%s</name>"
  673                               "<comment>%s</comment>"
  674                               "</create_task>",
  675                               config, target, name, comment);
  676   if (ret)
  677     return -1;
  678 
  679   /* Read the response. */
  680 
  681   ret = gmp_read_create_response (session, id);
  682   if (ret == 201)
  683     return 0;
  684   return ret;
  685 }
  686 
  687 /**
  688  * @brief Start a task and read the manager response.
  689  *
  690  * @param[in]   session    Pointer to GNUTLS session.
  691  * @param[in]   task_id    ID of task.
  692  * @param[out]  report_id  ID of report.
  693  *
  694  * @return 0 on success, 1 on failure, -1 on error.
  695  */
  696 int
  697 gmp_start_task_report (gnutls_session_t *session, const char *task_id,
  698                        char **report_id)
  699 {
  700   int ret;
  701   entity_t entity;
  702   if (gvm_server_sendf (session, "<start_task task_id=\"%s\"/>", task_id) == -1)
  703     return -1;
  704 
  705   /* Read the response. */
  706 
  707   entity = NULL;
  708   ret = gmp_check_response (session, &entity);
  709 
  710   if (ret == 0)
  711     {
  712       if (report_id)
  713         {
  714           entity_t report_id_xml = entity_child (entity, "report_id");
  715           if (report_id_xml)
  716             *report_id = g_strdup (entity_text (report_id_xml));
  717           else
  718             {
  719               free_entity (entity);
  720               return -1;
  721             }
  722         }
  723       free_entity (entity);
  724       return ret;
  725     }
  726   else if (ret == -1)
  727     return ret;
  728 
  729   return 1;
  730 }
  731 
  732 /**
  733  * @brief Start a task and read the manager response.
  734  *
  735  * @param[in]   connection  Connection.
  736  * @param[in]   task_id     ID of task.
  737  * @param[out]  report_id   ID of report.
  738  *
  739  * @return 0 on success, 1 on failure, -1 on error.
  740  */
  741 int
  742 gmp_start_task_report_c (gvm_connection_t *connection, const char *task_id,
  743                          char **report_id)
  744 {
  745   entity_t entity;
  746   const char *status;
  747   char first;
  748 
  749   if (gvm_connection_sendf (connection, "<start_task task_id=\"%s\"/>", task_id)
  750       == -1)
  751     return -1;
  752 
  753   /* Read the response. */
  754 
  755   entity = NULL;
  756   if (read_entity_c (connection, &entity))
  757     return -1;
  758 
  759   /* Check the response. */
  760 
  761   status = entity_attribute (entity, "status");
  762   if (status == NULL)
  763     {
  764       free_entity (entity);
  765       return -1;
  766     }
  767   if (strlen (status) == 0)
  768     {
  769       free_entity (entity);
  770       return -1;
  771     }
  772   first = status[0];
  773   if (first == '2')
  774     {
  775       if (report_id)
  776         {
  777           entity_t report_id_xml = entity_child (entity, "report_id");
  778           if (report_id_xml)
  779             *report_id = g_strdup (entity_text (report_id_xml));
  780           else
  781             {
  782               free_entity (entity);
  783               return -1;
  784             }
  785         }
  786       free_entity (entity);
  787       return 0;
  788     }
  789   free_entity (entity);
  790   return 1;
  791 }
  792 
  793 /**
  794  * @brief Read response and convert status of response to a return value.
  795  *
  796  * @param[in]  connection  Connection.
  797  *
  798  * @return 0 on success, -1 or GMP response code on error.
  799  */
  800 int
  801 gmp_check_response_c (gvm_connection_t *connection)
  802 {
  803   int ret;
  804   const char *status;
  805   entity_t entity;
  806 
  807   /* Read the response. */
  808 
  809   entity = NULL;
  810   if (read_entity_c (connection, &entity))
  811     return -1;
  812 
  813   /* Check the response. */
  814 
  815   status = entity_attribute (entity, "status");
  816   if (status == NULL)
  817     {
  818       free_entity (entity);
  819       return -1;
  820     }
  821   if (strlen (status) == 0)
  822     {
  823       free_entity (entity);
  824       return -1;
  825     }
  826   if (status[0] == '2')
  827     {
  828       free_entity (entity);
  829       return 0;
  830     }
  831   ret = (int) strtol (status, NULL, 10);
  832   free_entity (entity);
  833   if (errno == ERANGE)
  834     return -1;
  835   return ret;
  836 }
  837 
  838 /**
  839  * @brief Read response status and resource UUID.
  840  *
  841  * @param[in]  session  Pointer to GNUTLS session.
  842  * @param[out] uuid     Either NULL or address for freshly allocated UUID of
  843  *                      created response.
  844  *
  845  * @return GMP response code on success, -1 on error.
  846  */
  847 int
  848 gmp_read_create_response (gnutls_session_t *session, gchar **uuid)
  849 {
  850   int ret;
  851   const char *status;
  852   entity_t entity;
  853 
  854   /* Read the response. */
  855 
  856   entity = NULL;
  857   if (read_entity (session, &entity))
  858     return -1;
  859 
  860   /* Parse the response. */
  861 
  862   status = entity_attribute (entity, "status");
  863   if (status == NULL)
  864     {
  865       free_entity (entity);
  866       return -1;
  867     }
  868   if (strlen (status) == 0)
  869     {
  870       free_entity (entity);
  871       return -1;
  872     }
  873 
  874   if (uuid)
  875     {
  876       const char *id;
  877 
  878       id = entity_attribute (entity, "id");
  879       if (id == NULL)
  880         {
  881           free_entity (entity);
  882           return -1;
  883         }
  884       if (strlen (id) == 0)
  885         {
  886           free_entity (entity);
  887           return -1;
  888         }
  889       *uuid = g_strdup (id);
  890     }
  891 
  892   ret = atoi (status);
  893   free_entity (entity);
  894   return ret;
  895 }
  896 
  897 /**
  898  * @brief Stop a task and read the manager response.
  899  *
  900  * @param[in]  session  Pointer to GNUTLS session.
  901  * @param[in]  id       ID of task.
  902  *
  903  * @return 0 on success, GMP response code on failure, -1 on error.
  904  */
  905 int
  906 gmp_stop_task (gnutls_session_t *session, const char *id)
  907 {
  908   entity_t entity;
  909   int ret;
  910 
  911   if (gvm_server_sendf (session, "<stop_task task_id=\"%s\"/>", id) == -1)
  912     return -1;
  913 
  914   entity = NULL;
  915   ret = gmp_check_response (session, &entity);
  916   if (ret == 0)
  917     free_entity (entity);
  918   return ret;
  919 }
  920 
  921 /**
  922  * @brief Stop a task and read the manager response.
  923  *
  924  * @param[in]  connection  Connection.
  925  * @param[in]  id       ID of task.
  926  *
  927  * @return 0 on success, GMP response code on failure, -1 on error.
  928  */
  929 int
  930 gmp_stop_task_c (gvm_connection_t *connection, const char *id)
  931 {
  932   if (gvm_connection_sendf (connection, "<stop_task task_id=\"%s\"/>", id)
  933       == -1)
  934     return -1;
  935 
  936   return gmp_check_response_c (connection);
  937 }
  938 
  939 /**
  940  * @brief Resume a task and read the manager response.
  941  *
  942  * @param[in]   session    Pointer to GNUTLS session.
  943  * @param[in]   task_id    ID of task.
  944  * @param[out]  report_id  ID of report.
  945  *
  946  * @return 0 on success, 1 on GMP failure, -1 on error.
  947  */
  948 int
  949 gmp_resume_task_report (gnutls_session_t *session, const char *task_id,
  950                         char **report_id)
  951 {
  952   int ret;
  953   entity_t entity;
  954   if (gvm_server_sendf (session, "<resume_task task_id=\"%s\"/>", task_id)
  955       == -1)
  956     return -1;
  957 
  958   /* Read the response. */
  959 
  960   entity = NULL;
  961   ret = gmp_check_response (session, &entity);
  962 
  963   if (ret == 0)
  964     {
  965       if (report_id)
  966         {
  967           entity_t report_id_xml = entity_child (entity, "report_id");
  968           if (report_id_xml)
  969             *report_id = g_strdup (entity_text (report_id_xml));
  970           else
  971             {
  972               free_entity (entity);
  973               return -1;
  974             }
  975         }
  976       free_entity (entity);
  977       return 0;
  978     }
  979   else if (ret == -1)
  980     return ret;
  981   return 1;
  982 }
  983 
  984 /**
  985  * @brief Resume a task and read the manager response.
  986  *
  987  * @param[in]   connection  Connection.
  988  * @param[in]   task_id     ID of task.
  989  * @param[out]  report_id   ID of report.
  990  *
  991  * @return 0 on success, 1 on GMP failure, -1 on error.
  992  */
  993 int
  994 gmp_resume_task_report_c (gvm_connection_t *connection, const char *task_id,
  995                           char **report_id)
  996 {
  997   if (gvm_connection_sendf (connection, "<resume_task task_id=\"%s\"/>",
  998                             task_id)
  999       == -1)
 1000     return -1;
 1001 
 1002   /* Read the response. */
 1003 
 1004   entity_t entity = NULL;
 1005   if (read_entity_c (connection, &entity))
 1006     return -1;
 1007 
 1008   /* Check the response. */
 1009 
 1010   const char *status = entity_attribute (entity, "status");
 1011   if (status == NULL)
 1012     {
 1013       free_entity (entity);
 1014       return -1;
 1015     }
 1016   if (strlen (status) == 0)
 1017     {
 1018       free_entity (entity);
 1019       return -1;
 1020     }
 1021   char first = status[0];
 1022   if (first == '2')
 1023     {
 1024       if (report_id)
 1025         {
 1026           entity_t report_id_xml = entity_child (entity, "report_id");
 1027           if (report_id_xml)
 1028             *report_id = g_strdup (entity_text (report_id_xml));
 1029           else
 1030             {
 1031               free_entity (entity);
 1032               return -1;
 1033             }
 1034         }
 1035       free_entity (entity);
 1036       return 0;
 1037     }
 1038   free_entity (entity);
 1039   return 1;
 1040 }
 1041 
 1042 /**
 1043  * @brief Delete a task and read the manager response.
 1044  *
 1045  * @param[in]  session   Pointer to GNUTLS session.
 1046  * @param[in]  id        ID of task.
 1047  * @param[in]  opts      Struct containing the options to apply.
 1048  *
 1049  * @return 0 on success, GMP response code on failure, -1 on error.
 1050  */
 1051 int
 1052 gmp_delete_task_ext (gnutls_session_t *session, const char *id,
 1053                      gmp_delete_opts_t opts)
 1054 {
 1055   entity_t entity;
 1056   int ret;
 1057 
 1058   if (gvm_server_sendf (session,
 1059                         "<delete_task task_id=\"%s\" ultimate=\"%d\"/>", id,
 1060                         opts.ultimate)
 1061       == -1)
 1062     return -1;
 1063 
 1064   entity = NULL;
 1065   ret = gmp_check_response (session, &entity);
 1066   if (ret == 0)
 1067     free_entity (entity);
 1068   return ret;
 1069 }
 1070 
 1071 /**
 1072  * @brief Get the status of a task.
 1073  *
 1074  * @param[in]  session         Pointer to GNUTLS session.
 1075  * @param[in]  id              ID of task or NULL for all tasks.
 1076  * @param[in]  details         Whether to request task details.
 1077  * @param[in]  include_rcfile  Ignored.  Removed since GMP 6.0.
 1078  * @param[out] status          Status return.  On success contains GET_TASKS
 1079  *                             response.
 1080  *
 1081  * @return 0 on success, -1 or GMP response code on error.
 1082  */
 1083 int
 1084 gmp_get_tasks (gnutls_session_t *session, const char *id, int details,
 1085                int include_rcfile, entity_t *status)
 1086 {
 1087   (void) include_rcfile;
 1088   if (id == NULL)
 1089     {
 1090       if (gvm_server_sendf (session, "<get_tasks details=\"%i\"/>", details)
 1091           == -1)
 1092         return -1;
 1093     }
 1094   else
 1095     {
 1096       if (gvm_server_sendf (session,
 1097                             "<get_tasks"
 1098                             " task_id=\"%s\""
 1099                             " details=\"%i\"/>",
 1100                             id, details)
 1101           == -1)
 1102         return -1;
 1103     }
 1104 
 1105   /* Read the response. */
 1106   return gmp_check_response (session, status);
 1107 }
 1108 
 1109 /**
 1110  * @brief Get a task (generic version).
 1111  *
 1112  * @param[in]  session   Pointer to GNUTLS session.
 1113  * @param[in]  opts      Struct containing the options to apply.
 1114  * @param[out] response  Task.  On success contains GET_TASKS response.
 1115  *
 1116  * @return 0 on success, -1 or GMP response code on error.
 1117  */
 1118 int
 1119 gmp_get_task_ext (gnutls_session_t *session, gmp_get_task_opts_t opts,
 1120                   entity_t *response)
 1121 {
 1122   if ((response == NULL) || (opts.task_id == NULL))
 1123     return -1;
 1124 
 1125   if (opts.actions)
 1126     {
 1127       if (gvm_server_sendf (session,
 1128                             "<get_tasks"
 1129                             " task_id=\"%s\""
 1130                             " actions=\"%s\""
 1131                             "%s/>",
 1132                             opts.task_id, opts.actions,
 1133                             GMP_FMT_BOOL_ATTRIB (opts, details)))
 1134         return -1;
 1135     }
 1136   else if (gvm_server_sendf (session,
 1137                              "<get_tasks"
 1138                              " task_id=\"%s\""
 1139                              "%s/>",
 1140                              opts.task_id, GMP_FMT_BOOL_ATTRIB (opts, details)))
 1141     return -1;
 1142 
 1143   return gmp_check_response (session, response);
 1144 }
 1145 
 1146 /**
 1147  * @brief Get all tasks (generic version).
 1148  *
 1149  * @param[in]  session   Pointer to GNUTLS session.
 1150  * @param[in]  opts      Struct containing the options to apply.
 1151  * @param[out] response  Tasks.  On success contains GET_TASKS response.
 1152  *
 1153  * @return 0 on success, 2 on timeout, -1 or GMP response code on error.
 1154  */
 1155 int
 1156 gmp_get_tasks_ext (gnutls_session_t *session, gmp_get_tasks_opts_t opts,
 1157                    entity_t *response)
 1158 {
 1159   int ret;
 1160   const char *status_code;
 1161   gchar *cmd;
 1162 
 1163   if (response == NULL)
 1164     return -1;
 1165 
 1166   cmd = g_markup_printf_escaped ("<get_tasks"
 1167                                  " filter=\"%s\"",
 1168                                  opts.filter);
 1169 
 1170   if (gvm_server_sendf (session, "%s%s/>", cmd,
 1171                         GMP_FMT_BOOL_ATTRIB (opts, details)))
 1172     {
 1173       g_free (cmd);
 1174       return -1;
 1175     }
 1176   g_free (cmd);
 1177 
 1178   *response = NULL;
 1179   switch (try_read_entity (session, opts.timeout, response))
 1180     {
 1181     case 0:
 1182       break;
 1183     case -4:
 1184       return 2;
 1185     default:
 1186       return -1;
 1187     }
 1188 
 1189   /* Check the response. */
 1190 
 1191   status_code = entity_attribute (*response, "status");
 1192   if (status_code == NULL)
 1193     {
 1194       free_entity (*response);
 1195       return -1;
 1196     }
 1197   if (strlen (status_code) == 0)
 1198     {
 1199       free_entity (*response);
 1200       return -1;
 1201     }
 1202   if (status_code[0] == '2')
 1203     return 0;
 1204   ret = (int) strtol (status_code, NULL, 10);
 1205   free_entity (*response);
 1206   if (errno == ERANGE)
 1207     return -1;
 1208   return ret;
 1209 }
 1210 
 1211 /**
 1212  * @brief Modify a file on a task.
 1213  *
 1214  * @param[in]  session      Pointer to GNUTLS session.
 1215  * @param[in]  id           ID of task.
 1216  * @param[in]  name         Name of file.
 1217  * @param[in]  content      New content.  NULL to remove file.
 1218  * @param[in]  content_len  Length of content.
 1219  *
 1220  * @return 0 on success, -1 or GMP response code on error.
 1221  */
 1222 int
 1223 gmp_modify_task_file (gnutls_session_t *session, const char *id,
 1224                       const char *name, const void *content, gsize content_len)
 1225 {
 1226   entity_t entity;
 1227   int ret;
 1228 
 1229   if (name == NULL)
 1230     return -1;
 1231 
 1232   if (gvm_server_sendf (session, "<modify_task task_id=\"%s\">", id))
 1233     return -1;
 1234 
 1235   if (content)
 1236     {
 1237       if (gvm_server_sendf (session, "<file name=\"%s\" action=\"update\">",
 1238                             name))
 1239         return -1;
 1240 
 1241       if (content_len)
 1242         {
 1243           gchar *base64_content =
 1244             g_base64_encode ((guchar *) content, content_len);
 1245           int ret = gvm_server_sendf (session, "%s", base64_content);
 1246           g_free (base64_content);
 1247           if (ret)
 1248             return -1;
 1249         }
 1250 
 1251       if (gvm_server_sendf (session, "</file>"))
 1252         return -1;
 1253     }
 1254   else
 1255     {
 1256       if (gvm_server_sendf (session, "<file name=\"%s\" action=\"remove\" />",
 1257                             name))
 1258         return -1;
 1259     }
 1260 
 1261   if (gvm_server_sendf (session, "</modify_task>"))
 1262     return -1;
 1263 
 1264   entity = NULL;
 1265   ret = gmp_check_response (session, &entity);
 1266   if (ret == 0)
 1267     free_entity (entity);
 1268   return ret;
 1269 }
 1270 
 1271 /**
 1272  * @brief Delete a task and read the manager response.
 1273  *
 1274  * @param[in]  session  Pointer to GNUTLS session.
 1275  * @param[in]  id       ID of task.
 1276  *
 1277  * @return 0 on success, GMP response code on failure, -1 on error.
 1278  */
 1279 int
 1280 gmp_delete_task (gnutls_session_t *session, const char *id)
 1281 {
 1282   entity_t entity;
 1283   int ret;
 1284 
 1285   if (gvm_server_sendf (session, "<delete_task task_id=\"%s\"/>", id) == -1)
 1286     return -1;
 1287 
 1288   entity = NULL;
 1289   ret = gmp_check_response (session, &entity);
 1290   if (ret == 0)
 1291     free_entity (entity);
 1292   return ret;
 1293 }
 1294 
 1295 /**
 1296  * @brief Get a target.
 1297  *
 1298  * @param[in]  session         Pointer to GNUTLS session.
 1299  * @param[in]  id              ID of target or NULL for all targets.
 1300  * @param[in]  tasks           Whether to include tasks that use the target.
 1301  * @param[in]  include_rcfile  Not used.
 1302  * @param[out] target          Target return.  On success contains GET_TARGETS
 1303  *                             response.
 1304  *
 1305  * @return 0 on success, -1 or GMP response code on error.
 1306  */
 1307 int
 1308 gmp_get_targets (gnutls_session_t *session, const char *id, int tasks,
 1309                  int include_rcfile, entity_t *target)
 1310 {
 1311   (void) include_rcfile;
 1312   if (id == NULL)
 1313     {
 1314       if (gvm_server_sendf (session, "<get_targets tasks=\"%i\"/>", tasks)
 1315           == -1)
 1316         return -1;
 1317     }
 1318   else
 1319     {
 1320       if (gvm_server_sendf (session,
 1321                             "<get_targets"
 1322                             " target_id=\"%s\""
 1323                             " tasks=\"%i\"/>",
 1324                             id, tasks)
 1325           == -1)
 1326         return -1;
 1327     }
 1328 
 1329   /* Read the response. */
 1330   return gmp_check_response (session, target);
 1331 }
 1332 
 1333 /**
 1334  * @brief Get a report (generic version).
 1335  *
 1336  * FIXME: Using the according opts it should be possible to generate
 1337  * any type of get_reports request defined by the spec.
 1338  *
 1339  * @param[in]  session   Pointer to GNUTLS session.
 1340  * @param[in]  opts      Struct containing the options to apply.
 1341  * @param[out] response  Report.  On success contains GET_REPORT response.
 1342  *
 1343  * @return 0 on success, 2 on timeout, -1 or GMP response code on error.
 1344  */
 1345 int
 1346 gmp_get_report_ext (gnutls_session_t *session, gmp_get_report_opts_t opts,
 1347                     entity_t *response)
 1348 {
 1349   int ret;
 1350   const char *status_code;
 1351 
 1352   if (response == NULL)
 1353     return -1;
 1354 
 1355   if (gvm_server_sendf (
 1356         session,
 1357         "<get_reports"
 1358         " details=\"1\""
 1359         " report_id=\"%s\""
 1360         " format_id=\"%s\""
 1361         " host_first_result=\"%i\""
 1362         " host_max_results=\"%i\""
 1363         "%s%s%s"
 1364         "%s%s%s"
 1365         "%s%s%s"
 1366         "%s%s%s"
 1367         "%s%s%s"
 1368         "%s%s%s"
 1369         "%s%s%s"
 1370         "%s%s%s"
 1371         "%s%s%s"
 1372         "%s%s%s"
 1373         "%s%s%s"
 1374         "%s%s%s"
 1375         "%s%s%s"
 1376         "%s%s%s"
 1377         "%s%s%s%s%s%s%s/>",
 1378         opts.report_id, opts.format_id, opts.host_first_result,
 1379         opts.host_max_results, GMP_FMT_STRING_ATTRIB (opts, type),
 1380         GMP_FMT_STRING_ATTRIB (opts, filter),
 1381         GMP_FMT_STRING_ATTRIB (opts, filt_id),
 1382         GMP_FMT_STRING_ATTRIB (opts, host), GMP_FMT_STRING_ATTRIB (opts, pos),
 1383         GMP_FMT_STRING_ATTRIB (opts, timezone),
 1384         GMP_FMT_STRING_ATTRIB (opts, alert_id),
 1385         GMP_FMT_STRING_ATTRIB (opts, delta_report_id),
 1386         GMP_FMT_STRING_ATTRIB (opts, delta_states),
 1387         GMP_FMT_STRING_ATTRIB (opts, host_levels),
 1388         GMP_FMT_STRING_ATTRIB (opts, search_phrase),
 1389         GMP_FMT_STRING_ATTRIB (opts, host_search_phrase),
 1390         GMP_FMT_STRING_ATTRIB (opts, min_cvss_base),
 1391         GMP_FMT_STRING_ATTRIB (opts, min_qod),
 1392         GMP_FMT_BOOL_ATTRIB (opts, notes),
 1393         GMP_FMT_BOOL_ATTRIB (opts, notes_details),
 1394         GMP_FMT_BOOL_ATTRIB (opts, overrides),
 1395         GMP_FMT_BOOL_ATTRIB (opts, override_details),
 1396         GMP_FMT_BOOL_ATTRIB (opts, apply_overrides),
 1397         GMP_FMT_BOOL_ATTRIB (opts, result_hosts_only),
 1398         GMP_FMT_BOOL_ATTRIB (opts, ignore_pagination)))
 1399     return -1;
 1400 
 1401   *response = NULL;
 1402   switch (try_read_entity (session, opts.timeout, response))
 1403     {
 1404     case 0:
 1405       break;
 1406     case -4:
 1407       return 2;
 1408     default:
 1409       return -1;
 1410     }
 1411 
 1412   /* Check the response. */
 1413 
 1414   status_code = entity_attribute (*response, "status");
 1415   if (status_code == NULL)
 1416     {
 1417       free_entity (*response);
 1418       return -1;
 1419     }
 1420   if (strlen (status_code) == 0)
 1421     {
 1422       free_entity (*response);
 1423       return -1;
 1424     }
 1425   if (status_code[0] == '2')
 1426     return 0;
 1427   ret = (int) strtol (status_code, NULL, 10);
 1428   free_entity (*response);
 1429   if (errno == ERANGE)
 1430     return -1;
 1431   return ret;
 1432 }
 1433 
 1434 /**
 1435  * @brief Delete a port list.
 1436  *
 1437  * @param[in]   session     Pointer to GNUTLS session.
 1438  * @param[in]   id          UUID of port list.
 1439  * @param[in]   opts        Struct containing the options to apply.
 1440  *
 1441  * @return 0 on success, -1 or GMP response code on error.
 1442  */
 1443 int
 1444 gmp_delete_port_list_ext (gnutls_session_t *session, const char *id,
 1445                           gmp_delete_opts_t opts)
 1446 {
 1447   entity_t entity;
 1448   int ret;
 1449 
 1450   if (gvm_server_sendf (
 1451         session, "<delete_port_list port_list_id=\"%s\" ultimate=\"%d\"/>", id,
 1452         opts.ultimate)
 1453       == -1)
 1454     return -1;
 1455 
 1456   entity = NULL;
 1457   ret = gmp_check_response (session, &entity);
 1458   if (ret == 0)
 1459     free_entity (entity);
 1460   return ret;
 1461 }
 1462 
 1463 /**
 1464  * @brief Remove a report.
 1465  *
 1466  * @param[in]  session   Pointer to GNUTLS session.
 1467  * @param[in]  id        ID of report.
 1468  *
 1469  * @return 0 on success, GMP response code on failure, -1 on error.
 1470  */
 1471 int
 1472 gmp_delete_report (gnutls_session_t *session, const char *id)
 1473 {
 1474   entity_t entity;
 1475   int ret;
 1476 
 1477   if (gvm_server_sendf (session, "<delete_report report_id=\"%s\"/>", id))
 1478     return -1;
 1479 
 1480   entity = NULL;
 1481   ret = gmp_check_response (session, &entity);
 1482   if (ret == 0)
 1483     free_entity (entity);
 1484   return ret;
 1485 }
 1486 
 1487 /**
 1488  * @brief Create a target.
 1489  *
 1490  * FIXME: Using the according opts it should be possible to generate
 1491  * any type of create_target request defined by the spec.
 1492  *
 1493  * @param[in]  session   Pointer to GNUTLS session.
 1494  * @param[in]  opts      Struct containing the options to apply.
 1495  * @param[out] id        Pointer for newly allocated ID of new target, or NULL.
 1496  *                       Only set on successful return.
 1497  *
 1498  * @return 0 on success (GMP 201), -2 on connection error, GMP response code on
 1499  *         GMP error, -1 other error.
 1500  */
 1501 int
 1502 gmp_create_target_ext (gnutls_session_t *session, gmp_create_target_opts_t opts,
 1503                        gchar **id)
 1504 {
 1505   gchar *comment, *ssh, *smb, *esxi, *snmp, *port_range, *start;
 1506   gchar *exclude_hosts, *alive_tests;
 1507   int ret;
 1508 
 1509   /* Create the GMP request. */
 1510 
 1511   if (opts.hosts == NULL)
 1512     return -1;
 1513 
 1514   start =
 1515     g_markup_printf_escaped ("<create_target>"
 1516                              "<name>%s</name>"
 1517                              "<hosts>%s</hosts>",
 1518                              opts.name ? opts.name : "unnamed", opts.hosts);
 1519 
 1520   if (opts.exclude_hosts)
 1521     exclude_hosts = g_markup_printf_escaped ("<exclude_hosts>"
 1522                                              "%s"
 1523                                              "</exclude_hosts>",
 1524                                              opts.exclude_hosts);
 1525   else
 1526     exclude_hosts = NULL;
 1527 
 1528   if (opts.alive_tests)
 1529     alive_tests = g_markup_printf_escaped ("<alive_tests>"
 1530                                            "%s"
 1531                                            "</alive_tests>",
 1532                                            opts.alive_tests);
 1533   else
 1534     alive_tests = NULL;
 1535 
 1536   if (opts.comment)
 1537     comment = g_markup_printf_escaped ("<comment>"
 1538                                        "%s"
 1539                                        "</comment>",
 1540                                        opts.comment);
 1541   else
 1542     comment = NULL;
 1543 
 1544   if (opts.ssh_credential_id)
 1545     {
 1546       if (opts.ssh_credential_port)
 1547         ssh = g_markup_printf_escaped ("<ssh_lsc_credential id=\"%s\">"
 1548                                        "<port>%i</port>"
 1549                                        "</ssh_lsc_credential>",
 1550                                        opts.ssh_credential_id,
 1551                                        opts.ssh_credential_port);
 1552       else
 1553         ssh = g_markup_printf_escaped ("<ssh_lsc_credential id=\"%s\"/>",
 1554                                        opts.ssh_credential_id);
 1555     }
 1556   else
 1557     ssh = NULL;
 1558 
 1559   if (opts.smb_credential_id)
 1560     smb = g_markup_printf_escaped ("<smb_lsc_credential id=\"%s\"/>",
 1561                                    opts.smb_credential_id);
 1562   else
 1563     smb = NULL;
 1564 
 1565   if (opts.esxi_credential_id)
 1566     esxi = g_markup_printf_escaped ("<esxi_lsc_credential id=\"%s\"/>",
 1567                                     opts.esxi_credential_id);
 1568   else
 1569     esxi = NULL;
 1570 
 1571   if (opts.snmp_credential_id)
 1572     snmp = g_markup_printf_escaped ("<snmp_credential id=\"%s\"/>",
 1573                                     opts.snmp_credential_id);
 1574   else
 1575     snmp = NULL;
 1576 
 1577   if (opts.port_range)
 1578     port_range =
 1579       g_markup_printf_escaped ("<port_range>%s</port_range>", opts.port_range);
 1580   else
 1581     port_range = NULL;
 1582 
 1583   /* Send the request. */
 1584   ret = gvm_server_sendf (session,
 1585                           "%s%s%s%s%s%s%s%s%s"
 1586                           "<reverse_lookup_only>%d</reverse_lookup_only>"
 1587                           "<reverse_lookup_unify>%d</reverse_lookup_unify>"
 1588                           "</create_target>",
 1589                           start, exclude_hosts ? exclude_hosts : "",
 1590                           alive_tests ? alive_tests : "", ssh ? ssh : "",
 1591                           smb ? smb : "", esxi ? esxi : "", snmp ? snmp : "",
 1592                           port_range ? port_range : "", comment ? comment : "",
 1593                           opts.reverse_lookup_only, opts.reverse_lookup_unify);
 1594   g_free (start);
 1595   g_free (exclude_hosts);
 1596   g_free (alive_tests);
 1597   g_free (ssh);
 1598   g_free (smb);
 1599   g_free (esxi);
 1600   g_free (port_range);
 1601   g_free (comment);
 1602   if (ret)
 1603     return -2;
 1604 
 1605   /* Read the response. */
 1606 
 1607   ret = gmp_read_create_response (session, id);
 1608   if (ret == 201)
 1609     return 0;
 1610   return ret;
 1611 }
 1612 
 1613 /**
 1614  * @brief Delete a target.
 1615  *
 1616  * @param[in]   session     Pointer to GNUTLS session.
 1617  * @param[in]   id          UUID of target.
 1618  * @param[in]   opts        Struct containing the options to apply.
 1619  *
 1620  * @return 0 on success, -1 or GMP response code on error.
 1621  */
 1622 int
 1623 gmp_delete_target_ext (gnutls_session_t *session, const char *id,
 1624                        gmp_delete_opts_t opts)
 1625 {
 1626   entity_t entity;
 1627   int ret;
 1628 
 1629   if (gvm_server_sendf (session,
 1630                         "<delete_target target_id=\"%s\" ultimate=\"%d\"/>", id,
 1631                         opts.ultimate)
 1632       == -1)
 1633     return -1;
 1634 
 1635   entity = NULL;
 1636   ret = gmp_check_response (session, &entity);
 1637   if (ret == 0)
 1638     free_entity (entity);
 1639   return ret;
 1640 }
 1641 
 1642 /**
 1643  * @brief Delete a config.
 1644  *
 1645  * @param[in]   session     Pointer to GNUTLS session.
 1646  * @param[in]   id          UUID of config.
 1647  * @param[in]   opts        Struct containing the options to apply.
 1648  *
 1649  * @return 0 on success, -1 or GMP response code on error.
 1650  */
 1651 int
 1652 gmp_delete_config_ext (gnutls_session_t *session, const char *id,
 1653                        gmp_delete_opts_t opts)
 1654 {
 1655   entity_t entity;
 1656   int ret;
 1657 
 1658   if (gvm_server_sendf (session,
 1659                         "<delete_config config_id=\"%s\" ultimate=\"%d\"/>", id,
 1660                         opts.ultimate)
 1661       == -1)
 1662     return -1;
 1663 
 1664   entity = NULL;
 1665   ret = gmp_check_response (session, &entity);
 1666   if (ret == 0)
 1667     free_entity (entity);
 1668   return ret;
 1669 }
 1670 
 1671 /**
 1672  * @brief Create an LSC Credential.
 1673  *
 1674  * @param[in]   session   Pointer to GNUTLS session.
 1675  * @param[in]   name      Name of LSC Credential.
 1676  * @param[in]   login     Login associated with name.
 1677  * @param[in]   password  Password, or NULL for autogenerated credentials.
 1678  * @param[in]   comment   LSC Credential comment.
 1679  * @param[out]  uuid      Either NULL or address for UUID of created credential.
 1680  *
 1681  * @return 0 on success, -1 or GMP response code on error.
 1682  */
 1683 int
 1684 gmp_create_lsc_credential (gnutls_session_t *session, const char *name,
 1685                            const char *login, const char *password,
 1686                            const char *comment, gchar **uuid)
 1687 {
 1688   int ret;
 1689 
 1690   if (password)
 1691     {
 1692       if (comment)
 1693         ret = gvm_server_sendf_xml_quiet (session,
 1694                                           "<create_credential>"
 1695                                           "<name>%s</name>"
 1696                                           "<login>%s</login>"
 1697                                           "<password>%s</password>"
 1698                                           "<comment>%s</comment>"
 1699                                           "</create_credential>",
 1700                                           name, login, password, comment);
 1701       else
 1702         ret = gvm_server_sendf_xml_quiet (session,
 1703                                           "<create_credential>"
 1704                                           "<name>%s</name>"
 1705                                           "<login>%s</login>"
 1706                                           "<password>%s</password>"
 1707                                           "</create_credential>",
 1708                                           name, login, password);
 1709     }
 1710   else
 1711     {
 1712       if (comment)
 1713         ret = gvm_server_sendf_xml (session,
 1714                                     "<create_credential>"
 1715                                     "<name>%s</name>"
 1716                                     "<login>%s</login>"
 1717                                     "<comment>%s</comment>"
 1718                                     "</create_credential>",
 1719                                     name, login, comment);
 1720       else
 1721         ret = gvm_server_sendf_xml (session,
 1722                                     "<create_credential>"
 1723                                     "<name>%s</name>"
 1724                                     "<login>%s</login>"
 1725                                     "</create_credential>",
 1726                                     name, login);
 1727     }
 1728   if (ret)
 1729     return -1;
 1730 
 1731   ret = gmp_read_create_response (session, uuid);
 1732   if (ret == 201)
 1733     return 0;
 1734   return ret;
 1735 }
 1736 
 1737 /**
 1738  * @brief Create an LSC Credential with a key.
 1739  *
 1740  * @param[in]   session      Pointer to GNUTLS session.
 1741  * @param[in]   name         Name of LSC Credential.
 1742  * @param[in]   login        Login associated with name.
 1743  * @param[in]   passphrase   Passphrase for private key.
 1744  * @param[in]   private_key  Private key.
 1745  * @param[in]   comment      LSC Credential comment.
 1746  * @param[out]  uuid         Either NULL or address for UUID of created
 1747  *                           credential.
 1748  *
 1749  * @return 0 on success, -1 or GMP response code on error.
 1750  */
 1751 int
 1752 gmp_create_lsc_credential_key (gnutls_session_t *session, const char *name,
 1753                                const char *login, const char *passphrase,
 1754                                const char *private_key, const char *comment,
 1755                                gchar **uuid)
 1756 {
 1757   int ret;
 1758 
 1759   if (comment)
 1760     ret = gvm_server_sendf_xml (session,
 1761                                 "<create_credential>"
 1762                                 "<name>%s</name>"
 1763                                 "<login>%s</login>"
 1764                                 "<key>"
 1765                                 "<phrase>%s</phrase>"
 1766                                 "<private>%s</private>"
 1767                                 "</key>"
 1768                                 "<comment>%s</comment>"
 1769                                 "</create_credential>",
 1770                                 name, login, passphrase ? passphrase : "",
 1771                                 private_key, comment);
 1772   else
 1773     ret = gvm_server_sendf_xml (session,
 1774                                 "<create_credential>"
 1775                                 "<name>%s</name>"
 1776                                 "<login>%s</login>"
 1777                                 "<key>"
 1778                                 "<phrase>%s</phrase>"
 1779                                 "<private>%s</private>"
 1780                                 "</key>"
 1781                                 "</create_credential>",
 1782                                 name, login, passphrase ? passphrase : "",
 1783                                 private_key);
 1784 
 1785   if (ret)
 1786     return -1;
 1787 
 1788   ret = gmp_read_create_response (session, uuid);
 1789   if (ret == 201)
 1790     return 0;
 1791   return ret;
 1792 }
 1793 
 1794 /**
 1795  * @brief Create an LSC credential.
 1796  *
 1797  * @param[in]  session   Pointer to GNUTLS session.
 1798  * @param[in]  opts      Struct containing the options to apply.
 1799  * @param[out] id        Pointer for newly allocated ID of new LSC credential,
 1800  *                       or NULL.  Only set on successful return.
 1801  *
 1802  * @return 0 on success, -1 or GMP response code on error.
 1803  */
 1804 int
 1805 gmp_create_lsc_credential_ext (gnutls_session_t *session,
 1806                                gmp_create_lsc_credential_opts_t opts,
 1807                                gchar **id)
 1808 {
 1809   gchar *comment, *pass, *start, *snmp_elems;
 1810   int ret;
 1811 
 1812   /* Create the GMP request. */
 1813 
 1814   if (opts.login == NULL)
 1815     return -1;
 1816 
 1817   start =
 1818     g_markup_printf_escaped ("<create_credential>"
 1819                              "<name>%s</name>"
 1820                              "<login>%s</login>",
 1821                              opts.name ? opts.name : "unnamed", opts.login);
 1822 
 1823   if (opts.comment)
 1824     comment = g_markup_printf_escaped ("<comment>"
 1825                                        "%s"
 1826                                        "</comment>",
 1827                                        opts.comment);
 1828   else
 1829     comment = NULL;
 1830 
 1831   if (opts.private_key)
 1832     pass = g_markup_printf_escaped ("<key>"
 1833                                     "<phrase>%s</phrase>"
 1834                                     "<private>%s</private>"
 1835                                     "</key>",
 1836                                     opts.passphrase ? opts.passphrase : "",
 1837                                     opts.private_key);
 1838   else
 1839     {
 1840       if (opts.passphrase)
 1841         pass = g_markup_printf_escaped ("<password>"
 1842                                         "%s"
 1843                                         "</password>",
 1844                                         opts.passphrase);
 1845       else
 1846         pass = NULL;
 1847     }
 1848 
 1849   if (opts.community && opts.auth_algorithm && opts.privacy_password
 1850       && opts.privacy_algorithm)
 1851     snmp_elems =
 1852       g_markup_printf_escaped ("<community>"
 1853                                "%s"
 1854                                "</community>"
 1855                                "<auth_algorithm>"
 1856                                "%s"
 1857                                "</auth_algorithm>"
 1858                                "<privacy>"
 1859                                "<password>%s</password>"
 1860                                "<algorithm>%s</algorithm>"
 1861                                "</privacy>",
 1862                                opts.community, opts.auth_algorithm,
 1863                                opts.privacy_password, opts.privacy_algorithm);
 1864   else
 1865     snmp_elems = NULL;
 1866 
 1867   /* Send the request. */
 1868 
 1869   ret = gvm_server_sendf (session, "%s%s%s%s</create_credential>", start,
 1870                           comment ? comment : "", pass ? pass : "",
 1871                           snmp_elems ? snmp_elems : "");
 1872 
 1873   g_free (start);
 1874   g_free (comment);
 1875   g_free (pass);
 1876   if (ret)
 1877     return -1;
 1878 
 1879   /* Read the response. */
 1880 
 1881   ret = gmp_read_create_response (session, id);
 1882   if (ret == 201)
 1883     return 0;
 1884   return ret;
 1885 }
 1886 
 1887 /**
 1888  * @brief Delete a LSC credential.
 1889  *
 1890  * @param[in]   session     Pointer to GNUTLS session.
 1891  * @param[in]   id          UUID of LSC credential.
 1892  * @param[in]   opts        Struct containing the options to apply.
 1893  *
 1894  * @return 0 on success, -1 or GMP response code on error.
 1895  */
 1896 int
 1897 gmp_delete_lsc_credential_ext (gnutls_session_t *session, const char *id,
 1898                                gmp_delete_opts_t opts)
 1899 {
 1900   entity_t entity;
 1901   int ret;
 1902 
 1903   if (gvm_server_sendf (session,
 1904                         "<delete_credential credential_id=\"%s\""
 1905                         " ultimate=\"%d\"/>",
 1906                         id, opts.ultimate)
 1907       == -1)
 1908     return -1;
 1909 
 1910   entity = NULL;
 1911   ret = gmp_check_response (session, &entity);
 1912   if (ret == 0)
 1913     free_entity (entity);
 1914   return ret;
 1915 }
 1916 
 1917 /**
 1918  * @brief Get system reports.
 1919  *
 1920  * @param[in]  session  Pointer to GNUTLS session.
 1921  * @param[in]  name     Name of system report.  NULL for all.
 1922  * @param[in]  brief    Whether to request brief response.
 1923  * @param[out] reports  Reports return.  On success contains GET_SYSTEM_REPORTS
 1924  *                      response.
 1925  *
 1926  * @return 0 on success, -1 or GMP response code on error.
 1927  */
 1928 int
 1929 gmp_get_system_reports (gnutls_session_t *session, const char *name, int brief,
 1930                         entity_t *reports)
 1931 {
 1932   if (name)
 1933     {
 1934       if (gvm_server_sendf (session,
 1935                             "<get_system_reports name=\"%s\" brief=\"%i\"/>",
 1936                             name, brief)
 1937           == -1)
 1938         return -1;
 1939     }
 1940   else if (gvm_server_sendf (session, "<get_system_reports brief=\"%i\"/>",
 1941                              brief)
 1942            == -1)
 1943     return -1;
 1944 
 1945   /* Read and check the response. */
 1946   return gmp_check_response (session, reports);
 1947 }
 1948 
 1949 /**
 1950  * @brief Get system reports.
 1951  *
 1952  * @param[in]  session  Pointer to GNUTLS session.
 1953  * @param[in]  opts     Struct containing the options to apply.
 1954  * @param[out] reports  Reports return.  On success contains GET_SYSTEM_REPORTS
 1955  *                      response.
 1956  *
 1957  * @return 0 on success, -1 or GMP response code on error.
 1958  */
 1959 int
 1960 gmp_get_system_reports_ext (gnutls_session_t *session,
 1961                             gmp_get_system_reports_opts_t opts,
 1962                             entity_t *reports)
 1963 {
 1964   GString *request;
 1965 
 1966   request = g_string_new ("<get_system_reports");
 1967 
 1968   if (opts.slave_id)
 1969     xml_string_append (request, " slave_id=\"%s\"", opts.slave_id);
 1970 
 1971   if (opts.name)
 1972     xml_string_append (request, " name=\"%s\"", opts.name);
 1973 
 1974   if (opts.duration)
 1975     xml_string_append (request, " duration=\"%s\"", opts.duration);
 1976 
 1977   if (opts.start_time)
 1978     xml_string_append (request, " start_time=\"%s\"", opts.start_time);
 1979 
 1980   if (opts.end_time)
 1981     xml_string_append (request, " end_time=\"%s\"", opts.end_time);
 1982 
 1983   g_string_append (request, "/>");
 1984 
 1985   /* Create the GMP request. */
 1986 
 1987   if (gvm_server_sendf (session, "%s", request->str) == -1)
 1988     {
 1989       g_string_free (request, 1);
 1990       return -1;
 1991     }
 1992   g_string_free (request, 1);
 1993 
 1994   /* Read and check the response. */
 1995   return gmp_check_response (session, reports);
 1996 }