Greenbone Security Assistant  7.0.0
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 
81 int
83 {
84 #ifdef USE_LIBXSLT
85  if (!xmlHasFeature (XML_WITH_THREAD))
86  return 1;
87  /* Required by libxml for thread safety. */
88  xmlInitParser ();
89 #endif
90  return 0;
91 }
92 
98 int
100 {
101 #ifdef USE_LIBXSLT
102  xsltCleanupGlobals ();
103  xmlCleanupParser ();
104 #endif
105  return 0;
106 }
107 
113 int
115 {
116  return chroot_state;
117 }
118 
124 void
125 set_chroot_state (int state)
126 {
127  chroot_state = state;
128 }
129 
135 void
136 vendor_version_set (const gchar *version)
137 {
138  g_free (vendor_version);
139  vendor_version = g_strdup (version);
140 }
141 
147 const gchar *
149 {
150  return vendor_version ? vendor_version : "";
151 }
152 
158 const gchar *
160 {
161  return label_name;
162 }
163 
171 int
172 label_name_set (const gchar *name)
173 {
174  if (!g_regex_match_simple ("^[a-zA-Z0-9\\-_\\.\\:]+$", name, 0, 0))
175  return -1;
176 
177  g_free (label_name);
178  label_name = g_strdup (name);
179  return 0;
180 }
181 
190 void
191 set_language_code (gchar **lang, const gchar *language)
192 {
193  if (language == NULL || strcmp (language, "Browser Language") == 0)
194  *lang = NULL;
195  else if (strcmp (language, "Chinese") == 0)
196  *lang = g_strdup ("zh_CN");
197  else if (strcmp (language, "English") == 0)
198  *lang = g_strdup ("en");
199  else if (strcmp (language, "German") == 0)
200  *lang = g_strdup ("de");
201  else
202  *lang = g_strdup (language);
203 }
204 
213 char*
214 ctime_r_strip_newline (time_t *time, char *string)
215 {
216  struct tm *tm;
217 
218  tm = localtime (time);
219  if (tm == NULL
220  || (strftime (string,
221  199,
222  "%c %Z",
223  tm)
224  == 0))
225  {
226  string[0] = '\0';
227  return string;
228  }
229  return string;
230 }
231 
235 #define FAIL_HTML \
236  "<html>" \
237  "<body>" \
238  "An internal server error has occurred during XSL transformation." \
239  "</body>" \
240  "</html>"
241 
253 char *
254 xsl_transform_with_stylesheet (const char *xml_text,
255  const char *xsl_stylesheet,
256  cmd_response_data_t *response_data)
257 {
258 #ifdef USE_LIBXSLT
259  xsltStylesheetPtr cur = NULL;
260  xmlDocPtr doc, res;
261  xmlChar *doc_txt_ptr = NULL;
262  int doc_txt_len;
263 
264  g_debug ("xsl stylesheet: [%s]\n", xml_text);
265  g_debug ("text to transform: [%s]\n", xml_text);
266 
267  exsltRegisterAll ();
269 
270  xmlSubstituteEntitiesDefault (1);
271  xmlLoadExtDtdDefaultValue = 1;
272  cur = xsltParseStylesheetFile ((const xmlChar *) xsl_stylesheet);
273  if (cur == NULL)
274  {
275  g_warning ("Failed to parse stylesheet %s", xsl_stylesheet);
276  if (response_data)
277  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
278  return g_strdup (FAIL_HTML);
279  }
280 
281  doc = xmlParseMemory (xml_text, strlen (xml_text));
282  if (doc == NULL)
283  {
284  g_warning ("Failed to parse stylesheet %s", xsl_stylesheet);
285  xsltFreeStylesheet (cur);
286  if (response_data)
287  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
288  return g_strdup (FAIL_HTML);
289  }
290 
291  res = xsltApplyStylesheet (cur, doc, NULL);
292  if (res == NULL)
293  {
294  g_warning ("Failed to apply stylesheet %s", xsl_stylesheet);
295  xsltFreeStylesheet (cur);
296  xmlFreeDoc (doc);
297  if (response_data)
298  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
299  return g_strdup (FAIL_HTML);
300  }
301  xmlFreeDoc (doc);
302 
303  if (xsltSaveResultToString (&doc_txt_ptr, &doc_txt_len, res, cur) < 0)
304  {
305  g_warning ("Failed to store transformation result.");
306  xsltFreeStylesheet (cur);
307  xmlFreeDoc (res);
308  if (response_data)
309  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
310  return g_strdup (FAIL_HTML);
311  }
312 
313  xsltFreeStylesheet (cur);
314  xmlFreeDoc (res);
315  malloc_trim (0);
316 
317  return (char *) doc_txt_ptr;
318 #else
319  int content_fd;
320  gint exit_status;
321  gchar **cmd;
322  gboolean success = TRUE;
323  gchar *standard_out = NULL;
324  gchar *standard_err = NULL;
325  char content_file[] = "/tmp/gsa_xsl_transform_XXXXXX";
326  GError *error;
327 
328  /* Create a temporary file. */
329 
330  content_fd = mkstemp (content_file);
331  if (content_fd == -1)
332  {
333  g_warning ("%s: mkstemp: %s\n", __FUNCTION__, strerror (errno));
334  return g_strdup (FAIL_HTML);
335  }
336 
337  /* Copy text to temporary file. */
338 
339  g_debug ("text to transform: [%s]\n", xml_text);
340 
341  error = NULL;
342  g_file_set_contents (content_file, xml_text, strlen (xml_text), &error);
343  if (error)
344  {
345  g_warning ("%s", error->message);
346  g_error_free (error);
347  unlink (content_file);
348  close (content_fd);
349  return g_strdup (FAIL_HTML);
350  }
351 
352  /* Run xsltproc on the temporary file. */
353 
354  cmd = (gchar **) g_malloc (4 * sizeof (gchar *));
355  cmd[0] = g_strdup ("xsltproc");
356  cmd[1] = g_strdup (xsl_stylesheet);
357  cmd[2] = g_strdup (content_file);
358  cmd[3] = NULL;
359  g_debug ("%s: Spawning in parent dir: %s %s %s\n",
360  __FUNCTION__, cmd[0], cmd[1], cmd[2]);
361  if ((g_spawn_sync (NULL,
362  cmd,
363  NULL, /* Environment. */
364  G_SPAWN_SEARCH_PATH,
365  NULL, /* Setup function. */
366  NULL,
367  &standard_out,
368  &standard_err,
369  &exit_status,
370  NULL)
371  == FALSE)
372  || (WIFEXITED (exit_status) == 0)
373  || WEXITSTATUS (exit_status))
374  {
375  g_debug ("%s: failed to transform the xml: %d (WIF %i, WEX %i)",
376  __FUNCTION__,
377  exit_status,
378  WIFEXITED (exit_status),
379  WEXITSTATUS (exit_status));
380  g_debug ("%s: stderr: %s\n", __FUNCTION__, standard_err);
381  g_debug ("%s: stdout: %s\n", __FUNCTION__, standard_out);
382  success = FALSE;
383  }
384 
385  /* Cleanup. */
386 
387  g_free (cmd[0]);
388  g_free (cmd[1]);
389  g_free (cmd[2]);
390  g_free (cmd);
391  g_free (standard_err);
392 
393  unlink (content_file);
394  close (content_fd);
395 
396  if (success)
397  return standard_out;
398 
399  g_free (standard_out);
400 
401  if (response_data)
402  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
403  return g_strdup (FAIL_HTML);
404 #endif
405 }
406 
417 char *
418 xsl_transform (const char *xml_text, cmd_response_data_t *response_data)
419 {
420  return xsl_transform_with_stylesheet (xml_text, XSL_PATH, response_data);
421 }
422 
439 char *
440 gsad_message (credentials_t *credentials, const char *title,
441  const char *function, int line, const char *msg,
442  const char *backurl, cmd_response_data_t* response_data)
443 {
444  gchar *xml, *message, *resp;
445  const char* xml_flag;
446 
447  if (credentials && credentials->params)
448  xml_flag = params_value (credentials->params, "xml");
449  else
450  xml_flag = NULL;
451 
452  if (function)
453  {
454  message = g_strdup_printf ("<gsad_response>"
455  "<title>%s: %s:%i (GSA %s)</title>"
456  "<message>%s</message>"
457  "<backurl>%s</backurl>"
458  "<token>%s</token>"
459  "</gsad_response>",
460  title,
461  function,
462  line,
463  GSAD_VERSION,
464  msg,
465  backurl ? backurl : "/omp?cmd=get_tasks",
466  credentials ? credentials->token : "");
467  }
468  else
469  {
470  message = g_strdup_printf ("<gsad_response>"
471  "<title>%s (GSA %s)</title>"
472  "<message>%s</message>"
473  "<backurl>%s</backurl>"
474  "<token>%s</token>"
475  "</gsad_response>",
476  title,
477  GSAD_VERSION,
478  msg,
479  backurl ? backurl : "/omp?cmd=get_tasks",
480  credentials ? credentials->token : "");
481  }
482 
483  if (credentials)
484  {
485  gchar *pre;
486  time_t now;
487  char ctime_now[200];
488 
489  now = time (NULL);
490  ctime_r_strip_newline (&now, ctime_now);
491 
492  pre = g_markup_printf_escaped
493  ("<envelope>"
494  "<version>%s</version>"
495  "<vendor_version>%s</vendor_version>"
496  "<token>%s</token>"
497  "<time>%s</time>"
498  "<login>%s</login>"
499  "<role>%s</role>"
500  "<i18n>%s</i18n>"
501  "<charts>%i</charts>"
502  "<client_address>%s</client_address>",
503  GSAD_VERSION,
505  credentials->token,
506  ctime_now,
507  credentials->username,
508  credentials->role,
509  credentials->language,
510  credentials->charts,
511  credentials->client_address);
512  xml = g_strdup_printf ("%s%s"
513  "<capabilities>%s</capabilities>"
514  "</envelope>",
515  pre,
516  message,
517  credentials->capabilities);
518  g_free (pre);
519  }
520  else
521  {
522  xml = g_strdup (message);
523  }
524  g_free (message);
525 
526  if (xml_flag && strcmp (xml_flag, "0"))
527  return xml;
528 
529  resp = xsl_transform (xml, response_data);
530  if (resp == NULL)
531  {
532  resp = g_strdup ("<html>"
533  "<body>"
534  "An internal server error has occurred during XSL"
535  " transformation."
536  "</body>"
537  "</html>");
538  response_data->http_status_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
539  }
540  g_free (xml);
541  return resp;
542 }
543 
556 gchar *
557 login_xml (const gchar *message, const gchar *token, const gchar *time,
558  const gchar *url, const gchar *i18n, const gchar *guest)
559 {
560  GString *xml;
561  const gchar *label = label_name_get();
562 
563  xml = g_string_new ("");
564  xml_string_append (xml,
565  "<login_page>"
566  "<version>%s</version>"
567  "<vendor_version>%s</vendor_version>"
568  "<token>%s</token>"
569  "<time>%s</time>",
570  GSAD_VERSION,
572  token ? token : "",
573  time);
574 
575  if (label)
576  xml_string_append(xml,
577  "<label>%s</label>",
578  label);
579  if (message)
580  xml_string_append (xml,
581  "<message>%s</message>",
582  message);
583  if (url)
584  xml_string_append (xml,
585  "<url>%s</url>",
586  url);
587  if (i18n)
588  xml_string_append (xml,
589  "<i18n>%s</i18n>",
590  i18n);
591  if (guest)
592  xml_string_append (xml,
593  "<guest><username>%s</username></guest>",
594  guest);
595  g_string_append (xml, "</login_page>");
596 
597  return g_string_free (xml, FALSE);
598 }
599 
600 
601 /* Params. */
602 
608 static void
609 param_free (gpointer param)
610 {
611  g_free (((param_t*) param)->value);
612  g_free (((param_t*) param)->original_value);
613  g_free (((param_t*) param)->filename);
614  params_free (((param_t*)param)->values);
615  g_free (param);
616 }
617 
623 params_t *
625 {
626  return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, param_free);
627 }
628 
634 void
636 {
637  if (params)
638  g_hash_table_destroy (params);
639 }
640 
649 param_t *
650 params_get (params_t *params, const char *name)
651 {
652  param_t *param;
653  param = g_hash_table_lookup (params, name);
654  return param;
655 }
656 
665 int
666 params_given (params_t *params, const char *name)
667 {
668  param_t *param;
669  param = g_hash_table_lookup (params, name);
670  return param ? 1 : 0;
671 }
672 
681 const char *
682 params_value (params_t *params, const char *name)
683 {
684  param_t *param;
685  param = g_hash_table_lookup (params, name);
686  return param ? param->value : NULL;
687 }
688 
697 int
698 params_value_size (params_t *params, const char *name)
699 {
700  param_t *param;
701  param = g_hash_table_lookup (params, name);
702  return param ? param->value_size : -1;
703 }
704 
715 const char *
716 params_original_value (params_t *params, const char *name)
717 {
718  param_t *param;
719  param = g_hash_table_lookup (params, name);
720  return param ? param->original_value : NULL;
721 }
722 
731 const char *
732 params_filename (params_t *params, const char *name)
733 {
734  param_t *param;
735  param = g_hash_table_lookup (params, name);
736  return param ? param->filename : NULL;
737 }
738 
747 params_t *
748 params_values (params_t *params, const char *name)
749 {
750  param_t *param;
751  param = g_hash_table_lookup (params, name);
752  return param ? param->values : NULL;
753 }
754 
763 int
764 params_valid (params_t *params, const char *name)
765 {
766  param_t *param;
767  param = g_hash_table_lookup (params, name);
768  return param ? param->valid : 0;
769 }
770 
778 param_t *
779 params_add (params_t *params, const char *name, const char *value)
780 {
781  param_t *param;
782 
783  if (name == NULL)
784  name = "";
785  if (value == NULL)
786  value = "";
787 
788  param = g_malloc0 (sizeof (param_t));
789  param->valid = 0;
790  param->valid_utf8 = 0;
791  param->value = g_strdup (value);
792  param->value_size = strlen (value);
793  param->array_len = 0;
794  g_hash_table_insert (params, g_strdup (name), param);
795  return param;
796 }
797 
811 param_t *
812 params_append_bin (params_t *params, const char *name, const char *chunk_data,
813  int chunk_size, int chunk_offset)
814 {
815  param_t *param;
816  char *new_value;
817 
818  param = params_get (params, name);
819 
820  if (param == NULL)
821  {
822  char *value;
823 
824  value = g_malloc0 (chunk_size + 1);
825  memcpy (value + chunk_offset, chunk_data, chunk_size);
826 
827  param = params_add (params, name, "");
828  g_free (param->value);
829  param->value = value;
830  param->value_size = chunk_size;
831  return param;
832  }
833 
834  new_value = realloc (param->value,
835  param->value_size + chunk_size + 1);
836  if (new_value == NULL)
837  return NULL;
838  param->value = new_value;
839  memcpy (param->value + chunk_offset,
840  chunk_data,
841  chunk_size);
842  param->value[chunk_offset + chunk_size] = '\0';
843  param->value_size += chunk_size;
844 
845  return param;
846 }
847 
857 gboolean
858 params_iterator_next (params_iterator_t *iterator, char **name,
859  param_t **param)
860 {
861  return g_hash_table_iter_next (iterator, (gpointer*) name, (gpointer*) param);
862 }
int params_value_size(params_t *params, const char *name)
Get the size of the value of param.
Definition: gsad_base.c:698
params_t * params_values(params_t *params, const char *name)
Get values of param.
Definition: gsad_base.c:748
gchar * value
Definition: gsad_base.h:146
int gsad_base_cleanup()
Base init.
Definition: gsad_base.c:99
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:650
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:440
int params_given(params_t *params, const char *name)
Get whether a param was given at all.
Definition: gsad_base.c:666
Response information for commands.
Definition: gsad_base.h:92
#define FAIL_HTML
HTML returned when XSL transform fails.
Definition: gsad_base.c:235
int valid_utf8
Definition: gsad_base.h:151
gchar * filename
Definition: gsad_base.h:148
const char * params_filename(params_t *params, const char *name)
Get filename of param.
Definition: gsad_base.c:732
void params_free(params_t *params)
Make a params.
Definition: gsad_base.c:635
void set_chroot_state(int state)
Sets the chroot state.
Definition: gsad_base.c:125
void set_language_code(gchar **lang, const gchar *language)
Set language code of user.
Definition: gsad_base.c:191
gchar * label_name
Definition: gsad_base.c:69
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:716
gchar * original_value
Definition: gsad_base.h:147
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:152
void vendor_version_set(const gchar *version)
Set the vendor version.
Definition: gsad_base.c:136
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:557
int array_len
Definition: gsad_base.h:153
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:254
params_t * params_new()
Make a params.
Definition: gsad_base.c:624
#define params_t
Definition: gsad_base.h:61
int chroot_state
Whether chroot is used.
Definition: gsad.c:344
Request parameter.
Definition: gsad_base.h:144
int gsad_base_init()
Base init.
Definition: gsad_base.c:82
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:812
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:682
gboolean params_iterator_next(params_iterator_t *iterator, char **name, param_t **param)
Increment a params iterator.
Definition: gsad_base.c:858
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:148
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:418
int get_chroot_state()
Gets the chroot state.
Definition: gsad_base.c:114
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:150
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:214
#define params_iterator_t
Definition: gsad_base.h:185
int label_name_set(const gchar *name)
Set the login label.
Definition: gsad_base.c:172
params_t * values
Definition: gsad_base.h:149
param_t * params_add(params_t *params, const char *name, const char *value)
Add a param.
Definition: gsad_base.c:779
const gchar * label_name_get()
Get the login label name.
Definition: gsad_base.c:159
int params_valid(params_t *params, const char *name)
Get whether a param is valid.
Definition: gsad_base.c:764