Greenbone Security Assistant  7.0.3~git
gsad_base.c
Go to the documentation of this file.
1 /* Greenbone Security Assistant
2  * $Id$
3  * Description: Base functionalities of GSA.
4  *
5  * Authors:
6  * Matthew Mundell <matthew.mundell@greenbone.net>
7  * Jan-Oliver Wagner <jan-oliver.wagner@greenbone.net>
8  *
9  * Copyright:
10  * Copyright (C) 2009 Greenbone Networks GmbH
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26 
35 #define XSL_PATH "gsad.xsl"
36 
37 #include "gsad_base.h"
38 
39 #include <openvas/omp/xml.h>
40 
41 #include <glib.h>
42 #include <microhttpd.h> /* for HTTP status codes */
43 #ifdef USE_LIBXSLT
44 #include "xslt_i18n.h"
45 #include <libxml/parser.h>
46 #include <libexslt/exslt.h>
47 #include <string.h> /* for strlen() */
48 #include <libxslt/xsltInternals.h> /* for xsltStylesheetPtr */
49 #include <libxslt/transform.h> /* for xsltApplyStylesheet() */
50 #include <libxslt/xsltutils.h> /* for xsltSaveResultToString() */
51 #include <malloc.h>
52 #else
53 #include <string.h>
54 #include <sys/wait.h>
55 #include <errno.h>
56 #endif
57 
58 #undef G_LOG_DOMAIN
59 
62 #define G_LOG_DOMAIN "gsad base"
63 
67 gchar *vendor_version = NULL;
68 
69 gchar *label_name = NULL;
70 
74 static int chroot_state = 0;
75 
79 static int http_only = 0;
80 
86 int
88 {
89 #ifdef USE_LIBXSLT
90  if (!xmlHasFeature (XML_WITH_THREAD))
91  return 1;
92  /* Required by libxml for thread safety. */
93  xmlInitParser ();
94 #endif
95  return 0;
96 }
97 
103 int
105 {
106 #ifdef USE_LIBXSLT
107  xsltCleanupGlobals ();
108  xmlCleanupParser ();
109 #endif
110  return 0;
111 }
112 
118 int
120 {
121  return chroot_state;
122 }
123 
129 void
130 set_chroot_state (int state)
131 {
132  chroot_state = state;
133 }
134 
140 int
142 {
143  return http_only;
144 }
145 
151 void
152 set_http_only (int state)
153 {
154  http_only = state;
155 }
156 
162 void
163 vendor_version_set (const gchar *version)
164 {
165  g_free (vendor_version);
166  vendor_version = g_strdup (version);
167 }
168 
174 const gchar *
176 {
177  return vendor_version ? vendor_version : "";
178 }
179 
185 const gchar *
187 {
188  return label_name;
189 }
190 
198 int
199 label_name_set (const gchar *name)
200 {
201  if (!g_regex_match_simple ("^[a-zA-Z0-9\\-_\\.\\:]+$", name, 0, 0))
202  return -1;
203 
204  g_free (label_name);
205  label_name = g_strdup (name);
206  return 0;
207 }
208 
217 void
218 set_language_code (gchar **lang, const gchar *language)
219 {
220  if (language == NULL || strcmp (language, "Browser Language") == 0)
221  *lang = NULL;
222  else if (strcmp (language, "Chinese") == 0)
223  *lang = g_strdup ("zh_CN");
224  else if (strcmp (language, "English") == 0)
225  *lang = g_strdup ("en");
226  else if (strcmp (language, "German") == 0)
227  *lang = g_strdup ("de");
228  else
229  *lang = g_strdup (language);
230 }
231 
240 char*
241 ctime_r_strip_newline (time_t *time, char *string)
242 {
243  struct tm *tm;
244 
245  tm = localtime (time);
246  if (tm == NULL
247  || (strftime (string,
248  199,
249  "%c %Z",
250  tm)
251  == 0))
252  {
253  string[0] = '\0';
254  return string;
255  }
256  return string;
257 }
258 
262 #define FAIL_HTML \
263  "<html>" \
264  "<body>" \
265  "An internal server error has occurred during XSL transformation." \
266  "</body>" \
267  "</html>"
268 
280 char *
281 xsl_transform_with_stylesheet (const char *xml_text,
282  const char *xsl_stylesheet,
283  cmd_response_data_t *response_data)
284 {
285 #ifdef USE_LIBXSLT
286  xsltStylesheetPtr cur = NULL;
287  xmlDocPtr doc, res;
288  xmlChar *doc_txt_ptr = NULL;
289  int doc_txt_len;
290 
291  g_debug ("xsl stylesheet: [%s]\n", xml_text);
292  g_debug ("text to transform: [%s]\n", xml_text);
293 
294  exsltRegisterAll ();
296 
297  xmlSubstituteEntitiesDefault (1);
298  xmlLoadExtDtdDefaultValue = 1;
299  cur = xsltParseStylesheetFile ((const xmlChar *) xsl_stylesheet);
300  if (cur == NULL)
301  {
302  g_warning ("Failed to parse stylesheet %s", xsl_stylesheet);
303  if (response_data)
304  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
305  return g_strdup (FAIL_HTML);
306  }
307 
308  doc = xmlParseMemory (xml_text, strlen (xml_text));
309  if (doc == NULL)
310  {
311  g_warning ("Failed to parse stylesheet %s", xsl_stylesheet);
312  xsltFreeStylesheet (cur);
313  if (response_data)
314  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
315  return g_strdup (FAIL_HTML);
316  }
317 
318  res = xsltApplyStylesheet (cur, doc, NULL);
319  if (res == NULL)
320  {
321  g_warning ("Failed to apply stylesheet %s", xsl_stylesheet);
322  xsltFreeStylesheet (cur);
323  xmlFreeDoc (doc);
324  if (response_data)
325  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
326  return g_strdup (FAIL_HTML);
327  }
328  xmlFreeDoc (doc);
329 
330  if (xsltSaveResultToString (&doc_txt_ptr, &doc_txt_len, res, cur) < 0)
331  {
332  g_warning ("Failed to store transformation result.");
333  xsltFreeStylesheet (cur);
334  xmlFreeDoc (res);
335  if (response_data)
336  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
337  return g_strdup (FAIL_HTML);
338  }
339 
340  xsltFreeStylesheet (cur);
341  xmlFreeDoc (res);
342  malloc_trim (0);
343 
344  return (char *) doc_txt_ptr;
345 #else
346  int content_fd;
347  gint exit_status;
348  gchar **cmd;
349  gboolean success = TRUE;
350  gchar *standard_out = NULL;
351  gchar *standard_err = NULL;
352  char content_file[] = "/tmp/gsa_xsl_transform_XXXXXX";
353  GError *error;
354 
355  /* Create a temporary file. */
356 
357  content_fd = mkstemp (content_file);
358  if (content_fd == -1)
359  {
360  g_warning ("%s: mkstemp: %s\n", __FUNCTION__, strerror (errno));
361  return g_strdup (FAIL_HTML);
362  }
363 
364  /* Copy text to temporary file. */
365 
366  g_debug ("text to transform: [%s]\n", xml_text);
367 
368  error = NULL;
369  g_file_set_contents (content_file, xml_text, strlen (xml_text), &error);
370  if (error)
371  {
372  g_warning ("%s", error->message);
373  g_error_free (error);
374  unlink (content_file);
375  close (content_fd);
376  return g_strdup (FAIL_HTML);
377  }
378 
379  /* Run xsltproc on the temporary file. */
380 
381  cmd = (gchar **) g_malloc (4 * sizeof (gchar *));
382  cmd[0] = g_strdup ("xsltproc");
383  cmd[1] = g_strdup (xsl_stylesheet);
384  cmd[2] = g_strdup (content_file);
385  cmd[3] = NULL;
386  g_debug ("%s: Spawning in parent dir: %s %s %s\n",
387  __FUNCTION__, cmd[0], cmd[1], cmd[2]);
388  if ((g_spawn_sync (NULL,
389  cmd,
390  NULL, /* Environment. */
391  G_SPAWN_SEARCH_PATH,
392  NULL, /* Setup function. */
393  NULL,
394  &standard_out,
395  &standard_err,
396  &exit_status,
397  NULL)
398  == FALSE)
399  || (WIFEXITED (exit_status) == 0)
400  || WEXITSTATUS (exit_status))
401  {
402  g_debug ("%s: failed to transform the xml: %d (WIF %i, WEX %i)",
403  __FUNCTION__,
404  exit_status,
405  WIFEXITED (exit_status),
406  WEXITSTATUS (exit_status));
407  g_debug ("%s: stderr: %s\n", __FUNCTION__, standard_err);
408  g_debug ("%s: stdout: %s\n", __FUNCTION__, standard_out);
409  success = FALSE;
410  }
411 
412  /* Cleanup. */
413 
414  g_free (cmd[0]);
415  g_free (cmd[1]);
416  g_free (cmd[2]);
417  g_free (cmd);
418  g_free (standard_err);
419 
420  unlink (content_file);
421  close (content_fd);
422 
423  if (success)
424  return standard_out;
425 
426  g_free (standard_out);
427 
428  if (response_data)
429  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
430  return g_strdup (FAIL_HTML);
431 #endif
432 }
433 
444 char *
445 xsl_transform (const char *xml_text, cmd_response_data_t *response_data)
446 {
447  return xsl_transform_with_stylesheet (xml_text, XSL_PATH, response_data);
448 }
449 
466 char *
467 gsad_message (credentials_t *credentials, const char *title,
468  const char *function, int line, const char *msg,
469  const char *backurl, cmd_response_data_t* response_data)
470 {
471  gchar *xml, *message, *resp;
472  const char* xml_flag;
473 
474  if (credentials && credentials->params)
475  xml_flag = params_value (credentials->params, "xml");
476  else
477  xml_flag = NULL;
478 
479  if (function)
480  {
481  message = g_strdup_printf ("<gsad_response>"
482  "<title>%s: %s:%i (GSA %s)</title>"
483  "<message>%s</message>"
484  "<backurl>%s</backurl>"
485  "<token>%s</token>"
486  "</gsad_response>",
487  title,
488  function,
489  line,
490  GSAD_VERSION,
491  msg,
492  backurl ? backurl : "/omp?cmd=get_tasks",
493  credentials ? credentials->token : "");
494  }
495  else
496  {
497  message = g_strdup_printf ("<gsad_response>"
498  "<title>%s (GSA %s)</title>"
499  "<message>%s</message>"
500  "<backurl>%s</backurl>"
501  "<token>%s</token>"
502  "</gsad_response>",
503  title,
504  GSAD_VERSION,
505  msg,
506  backurl ? backurl : "/omp?cmd=get_tasks",
507  credentials ? credentials->token : "");
508  }
509 
510  if (credentials)
511  {
512  gchar *pre;
513  time_t now;
514  char ctime_now[200];
515 
516  now = time (NULL);
517  ctime_r_strip_newline (&now, ctime_now);
518 
519  pre = g_markup_printf_escaped
520  ("<envelope>"
521  "<version>%s</version>"
522  "<vendor_version>%s</vendor_version>"
523  "<token>%s</token>"
524  "<time>%s</time>"
525  "<login>%s</login>"
526  "<role>%s</role>"
527  "<i18n>%s</i18n>"
528  "<charts>%i</charts>"
529  "<client_address>%s</client_address>",
530  GSAD_VERSION,
532  credentials->token,
533  ctime_now,
534  credentials->username,
535  credentials->role,
536  credentials->language,
537  credentials->charts,
538  credentials->client_address);
539  xml = g_strdup_printf ("%s%s"
540  "<capabilities>%s</capabilities>"
541  "</envelope>",
542  pre,
543  message,
544  credentials->capabilities);
545  g_free (pre);
546  }
547  else
548  {
549  xml = g_strdup (message);
550  }
551  g_free (message);
552 
553  if (xml_flag && strcmp (xml_flag, "0"))
554  return xml;
555 
556  resp = xsl_transform (xml, response_data);
557  if (resp == NULL)
558  {
559  resp = g_strdup ("<html>"
560  "<body>"
561  "An internal server error has occurred during XSL"
562  " transformation."
563  "</body>"
564  "</html>");
565  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
566  }
567  g_free (xml);
568  return resp;
569 }
570 
583 gchar *
584 login_xml (const gchar *message, const gchar *token, const gchar *time,
585  const gchar *url, const gchar *i18n, const gchar *guest)
586 {
587  GString *xml;
588  const gchar *label = label_name_get();
589 
590  xml = g_string_new ("");
591  xml_string_append (xml,
592  "<login_page>"
593  "<version>%s</version>"
594  "<vendor_version>%s</vendor_version>"
595  "<token>%s</token>"
596  "<http_only>%d</http_only>"
597  "<time>%s</time>",
598  GSAD_VERSION,
600  token ? token : "",
601  get_http_only (),
602  time);
603 
604  if (label)
605  xml_string_append(xml,
606  "<label>%s</label>",
607  label);
608  if (message)
609  xml_string_append (xml,
610  "<message>%s</message>",
611  message);
612  if (url)
613  xml_string_append (xml,
614  "<url>%s</url>",
615  url);
616  if (i18n)
617  xml_string_append (xml,
618  "<i18n>%s</i18n>",
619  i18n);
620  if (guest)
621  xml_string_append (xml,
622  "<guest><username>%s</username></guest>",
623  guest);
624  g_string_append (xml, "</login_page>");
625 
626  return g_string_free (xml, FALSE);
627 }
628 
629 
630 /* Params. */
631 
637 static void
638 param_free (gpointer param)
639 {
640  g_free (((param_t*) param)->value);
641  g_free (((param_t*) param)->original_value);
642  g_free (((param_t*) param)->filename);
643  params_free (((param_t*)param)->values);
644  g_free (param);
645 }
646 
652 params_t *
654 {
655  return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, param_free);
656 }
657 
663 void
665 {
666  if (params)
667  g_hash_table_destroy (params);
668 }
669 
678 param_t *
679 params_get (params_t *params, const char *name)
680 {
681  param_t *param;
682  param = g_hash_table_lookup (params, name);
683  return param;
684 }
685 
694 int
695 params_given (params_t *params, const char *name)
696 {
697  param_t *param;
698  param = g_hash_table_lookup (params, name);
699  return param ? 1 : 0;
700 }
701 
710 const char *
711 params_value (params_t *params, const char *name)
712 {
713  param_t *param;
714  param = g_hash_table_lookup (params, name);
715  return param ? param->value : NULL;
716 }
717 
726 int
727 params_value_size (params_t *params, const char *name)
728 {
729  param_t *param;
730  param = g_hash_table_lookup (params, name);
731  return param ? param->value_size : -1;
732 }
733 
744 const char *
745 params_original_value (params_t *params, const char *name)
746 {
747  param_t *param;
748  param = g_hash_table_lookup (params, name);
749  return param ? param->original_value : NULL;
750 }
751 
760 const char *
761 params_filename (params_t *params, const char *name)
762 {
763  param_t *param;
764  param = g_hash_table_lookup (params, name);
765  return param ? param->filename : NULL;
766 }
767 
776 params_t *
777 params_values (params_t *params, const char *name)
778 {
779  param_t *param;
780  param = g_hash_table_lookup (params, name);
781  return param ? param->values : NULL;
782 }
783 
792 int
793 params_valid (params_t *params, const char *name)
794 {
795  param_t *param;
796  param = g_hash_table_lookup (params, name);
797  return param ? param->valid : 0;
798 }
799 
807 param_t *
808 params_add (params_t *params, const char *name, const char *value)
809 {
810  param_t *param;
811 
812  if (name == NULL)
813  name = "";
814  if (value == NULL)
815  value = "";
816 
817  param = g_malloc0 (sizeof (param_t));
818  param->valid = 0;
819  param->valid_utf8 = 0;
820  param->value = g_strdup (value);
821  param->value_size = strlen (value);
822  param->array_len = 0;
823  g_hash_table_insert (params, g_strdup (name), param);
824  return param;
825 }
826 
840 param_t *
841 params_append_bin (params_t *params, const char *name, const char *chunk_data,
842  int chunk_size, int chunk_offset)
843 {
844  param_t *param;
845  char *new_value;
846 
847  param = params_get (params, name);
848 
849  if (param == NULL)
850  {
851  char *value;
852 
853  value = g_malloc0 (chunk_size + 1);
854  memcpy (value + chunk_offset, chunk_data, chunk_size);
855 
856  param = params_add (params, name, "");
857  g_free (param->value);
858  param->value = value;
859  param->value_size = chunk_size;
860  return param;
861  }
862 
863  new_value = realloc (param->value,
864  param->value_size + chunk_size + 1);
865  if (new_value == NULL)
866  return NULL;
867  param->value = new_value;
868  memcpy (param->value + chunk_offset,
869  chunk_data,
870  chunk_size);
871  param->value[chunk_offset + chunk_size] = '\0';
872  param->value_size += chunk_size;
873 
874  return param;
875 }
876 
886 gboolean
887 params_iterator_next (params_iterator_t *iterator, char **name,
888  param_t **param)
889 {
890  return g_hash_table_iter_next (iterator, (gpointer*) name, (gpointer*) param);
891 }
int params_value_size(params_t *params, const char *name)
Get the size of the value of param.
Definition: gsad_base.c:727
params_t * params_values(params_t *params, const char *name)
Get values of param.
Definition: gsad_base.c:777
gchar * value
Definition: gsad_base.h:148
int gsad_base_cleanup()
Base init.
Definition: gsad_base.c:104
char * capabilities
Capabilites of manager.
Definition: gsad_base.h:76
param_t * params_get(params_t *params, const char *name)
Get param.
Definition: gsad_base.c:679
char * gsad_message(credentials_t *credentials, const char *title, const char *function, int line, const char *msg, const char *backurl, cmd_response_data_t *response_data)
Handles fatal errors.
Definition: gsad_base.c:467
int params_given(params_t *params, const char *name)
Get whether a param was given at all.
Definition: gsad_base.c:695
Response information for commands.
Definition: gsad_base.h:92
#define FAIL_HTML
HTML returned when XSL transform fails.
Definition: gsad_base.c:262
int valid_utf8
Definition: gsad_base.h:153
gchar * filename
Definition: gsad_base.h:150
const char * params_filename(params_t *params, const char *name)
Get filename of param.
Definition: gsad_base.c:761
void params_free(params_t *params)
Make a params.
Definition: gsad_base.c:664
void set_chroot_state(int state)
Sets the chroot state.
Definition: gsad_base.c:130
void set_language_code(gchar **lang, const gchar *language)
Set language code of user.
Definition: gsad_base.c:218
gchar * label_name
Definition: gsad_base.c:69
void set_http_only(int state)
Sets the http_only state.
Definition: gsad_base.c:152
Structure of credential related information.
Definition: gsad_base.h:66
const char * params_original_value(params_t *params, const char *name)
Get original value of param, before validation.
Definition: gsad_base.c:745
int get_http_only()
Gets the http_only state.
Definition: gsad_base.c:141
gchar * original_value
Definition: gsad_base.h:149
char * username
Name of user.
Definition: gsad_base.h:69
void register_i18n_ext_module()
Register the i18n XSLT extension module.
Definition: xslt_i18n.c:533
char * client_address
Client's address.
Definition: gsad_base.h:80
Headers/structs used generally in GSA.
int value_size
Definition: gsad_base.h:154
void vendor_version_set(const gchar *version)
Set the vendor version.
Definition: gsad_base.c:163
gchar * login_xml(const gchar *message, const gchar *token, const gchar *time, const gchar *url, const gchar *i18n, const gchar *guest)
Generate XML for login page.
Definition: gsad_base.c:584
int array_len
Definition: gsad_base.h:155
char * xsl_transform_with_stylesheet(const char *xml_text, const char *xsl_stylesheet, cmd_response_data_t *response_data)
XSL Transformation.
Definition: gsad_base.c:281
params_t * params_new()
Make a params.
Definition: gsad_base.c:653
#define params_t
Definition: gsad_base.h:61
int chroot_state
Whether chroot is used.
Definition: gsad.c:375
Request parameter.
Definition: gsad_base.h:146
int gsad_base_init()
Base init.
Definition: gsad_base.c:87
param_t * params_append_bin(params_t *params, const char *name, const char *chunk_data, int chunk_size, int chunk_offset)
Append binary data to a param.
Definition: gsad_base.c:841
char * token
Session token.
Definition: gsad_base.h:73
const char * params_value(params_t *params, const char *name)
Get value of param.
Definition: gsad_base.c:711
gboolean params_iterator_next(params_iterator_t *iterator, char **name, param_t **param)
Increment a params iterator.
Definition: gsad_base.c:887
char * role
User's role.
Definition: gsad_base.h:71
#define XSL_PATH
Location of XSL file.
Definition: gsad_base.c:35
const gchar * vendor_version_get()
Get the vendor version.
Definition: gsad_base.c:175
int charts
Whether to show charts for this user.
Definition: gsad_base.h:85
char * xsl_transform(const char *xml_text, cmd_response_data_t *response_data)
XSL Transformation.
Definition: gsad_base.c:445
int get_chroot_state()
Gets the chroot state.
Definition: gsad_base.c:119
char * language
Accept-Language browser header.
Definition: gsad_base.h:77
gchar * vendor_version
Version from vendor, or NULL.
Definition: gsad_base.c:67
int valid
Definition: gsad_base.h:152
params_t * params
Request parameters.
Definition: gsad_base.h:84
char * ctime_r_strip_newline(time_t *time, char *string)
Return string from ctime_r with newline replaces with terminator.
Definition: gsad_base.c:241
#define params_iterator_t
Definition: gsad_base.h:187
int label_name_set(const gchar *name)
Set the login label.
Definition: gsad_base.c:199
params_t * values
Definition: gsad_base.h:151
param_t * params_add(params_t *params, const char *name, const char *value)
Add a param.
Definition: gsad_base.c:808
const gchar * label_name_get()
Get the login label name.
Definition: gsad_base.c:186
int params_valid(params_t *params, const char *name)
Get whether a param is valid.
Definition: gsad_base.c:793