[Openvas-commits] r3179 - in trunk/openvas-config-manager: . src

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri Apr 24 11:37:51 CEST 2009


Author: mwiegand
Date: 2009-04-24 11:37:51 +0200 (Fri, 24 Apr 2009)
New Revision: 3179

Modified:
   trunk/openvas-config-manager/ChangeLog
   trunk/openvas-config-manager/src/CMakeLists.txt
   trunk/openvas-config-manager/src/openvascd.c
Log:
Added daemon functionality to openvascd. openvascd will now start as
GnuTLS server when started with the -d option.

* src/openvascd.c: (print_preference, print_user) The convenience
functions no longer print the output to stdout but collect them in a
GString. (main) Added support for daemon mode. Made output more
consistent, output now uses XML exclusively. (print_preferences_xml,
print_users_xml) Added functions to create ocp_response elements.
(initialize_tls_session, generate_dh_params) Added GnuTLS support
functions.

* CMakeLists.txt: Make sure OPENVAS_SERVER_CERTIFICATE,
OPENVAS_SERVER_KEY and OPENVAS_CA_CERTIFICATE are available when
compiling. Added link flag for GnuTLS.


Modified: trunk/openvas-config-manager/ChangeLog
===================================================================
--- trunk/openvas-config-manager/ChangeLog	2009-04-24 09:00:26 UTC (rev 3178)
+++ trunk/openvas-config-manager/ChangeLog	2009-04-24 09:37:51 UTC (rev 3179)
@@ -1,3 +1,20 @@
+2009-04-24  Michael Wiegand <michael.wiegand at intevation>
+
+	Added daemon functionality to openvascd. openvascd will now start as
+	GnuTLS server when started with the -d option.
+
+	* src/openvascd.c: (print_preference, print_user) The convenience
+	functions no longer print the output to stdout but collect them in a
+	GString. (main) Added support for daemon mode. Made output more
+	consistent, output now uses XML exclusively. (print_preferences_xml,
+	print_users_xml) Added functions to create ocp_response elements.
+	(initialize_tls_session, generate_dh_params) Added GnuTLS support
+	functions.
+
+	* CMakeLists.txt: Make sure OPENVAS_SERVER_CERTIFICATE,
+	OPENVAS_SERVER_KEY and OPENVAS_CA_CERTIFICATE are available when
+	compiling. Added link flag for GnuTLS.
+
 2009-04-22  Michael Wiegand <michael.wiegand at intevation>
 
 	Added support for retrieving server preferences (new command:

Modified: trunk/openvas-config-manager/src/CMakeLists.txt
===================================================================
--- trunk/openvas-config-manager/src/CMakeLists.txt	2009-04-24 09:00:26 UTC (rev 3178)
+++ trunk/openvas-config-manager/src/CMakeLists.txt	2009-04-24 09:37:51 UTC (rev 3179)
@@ -50,6 +50,18 @@
   add_definitions (-DOPENVAS_CONFIG_FILE=\\\"${OPENVAS_CONFIG_FILE}\\\")
 endif (OPENVAS_CONFIG_FILE)
 
+if (OPENVAS_SERVER_CERTIFICATE)
+  add_definitions (-DOPENVAS_SERVER_CERTIFICATE=\\\"${OPENVAS_SERVER_CERTIFICATE}\\\")
+endif (OPENVAS_SERVER_CERTIFICATE)
+
+if (OPENVAS_SERVER_KEY)
+  add_definitions (-DOPENVAS_SERVER_KEY=\\\"${OPENVAS_SERVER_KEY}\\\")
+endif (OPENVAS_SERVER_KEY)
+
+if (OPENVAS_CA_CERTIFICATE)
+  add_definitions (-DOPENVAS_CA_CERTIFICATE=\\\"${OPENVAS_CA_CERTIFICATE}\\\")
+endif (OPENVAS_CA_CERTIFICATE)
+
 add_definitions (-DOPENVAS_OS_NAME=\\\"${CMAKE_SYSTEM}\\\")
 add_definitions (-DPREFIX=\\\"${CMAKE_INSTALL_PREFIX}\\\")
 
@@ -60,7 +72,7 @@
 endif (OPENVAS_LIB_INSTALL_DIR)
 
 set_target_properties (openvascd PROPERTIES LINK_FLAGS
-                       "${TEMP} ${GLIB_LDFLAGS}")
+                       "${TEMP} -lgnutls ${GLIB_LDFLAGS}")
 
 if (OPENVAS_HEADER_INSTALL_DIR)
   set (TEMP "-I${OPENVAS_HEADER_INSTALL_DIR}")

Modified: trunk/openvas-config-manager/src/openvascd.c
===================================================================
--- trunk/openvas-config-manager/src/openvascd.c	2009-04-24 09:00:26 UTC (rev 3178)
+++ trunk/openvas-config-manager/src/openvascd.c	2009-04-24 09:37:51 UTC (rev 3179)
@@ -35,13 +35,44 @@
 #include <glib/gprintf.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
 
+#define OPENVASCD_DEFAULT_PORT 9392
+
+#define SA struct sockaddr
+#define SOCKET_ERR(err,s) if(err==-1) {perror(s);return(1);}
+#define MAX_BUF 1024
+#define DH_BITS 1024
+
+/* Global variables for GnuTLS */
+gnutls_certificate_credentials_t x509_cred;
+static gnutls_dh_params_t dh_params;
+
+gnutls_session_t
+initialize_tls_session (void);
+
+static void
+generate_dh_params (void);
+
 GSList *
 openvas_config_list_users (const gchar *);
 
 GHashTable *
 openvas_config_list_all_prefs (const gchar *);
 
+GString *
+print_preferences_xml (GHashTable *);
+
+GString *
+print_users_xml (GSList *);
+
 /**
  * @brief Convenience function to produce XML output from key/value pairs of
  * preferences.
@@ -49,15 +80,14 @@
  *
  * @param key The key.
  * @param value The value corresponding to the key.
- * @param user_data User data passed to g_hash_table_foreach(). (Currently
- * unused)
+ * @param user_data User data passed to g_hash_table_foreach().
  */
 void
 print_preference (void * key, void * value, void * user_data)
 {
-  g_printf (g_markup_printf_escaped ("<preference name=\"%s\">%s</preference>",
-                                     (gchar *) key, (gchar *) value));
-  g_printf ("\n");
+  user_data = g_string_append ((GString *) user_data,
+                               g_markup_printf_escaped ("<preference name=\"%s\">%s</preference>",
+                                                        (gchar *) key, (gchar *) value));
 }
 
 /**
@@ -65,15 +95,14 @@
  * This function is used by g_slist_foreach().
  *
  * @param data The item's data.
- * @param user_data User data passed to g_slist_foreach(). (Currently
- * unused)
+ * @param user_data User data passed to g_slist_foreach().
  */
 void
 print_user (void * data, void * user_data)
 {
-  g_printf (g_markup_printf_escaped ("<user>""<name>%s</name>" "<rules/>" "</user>",
-                                     (gchar *) data));
-  g_printf ("\n");
+  user_data = g_string_append ((GString *) user_data,
+                               g_markup_printf_escaped ("<user><name>%s</name><rules/></user>",
+                                                        (gchar *) data));
 }
 
 int
@@ -81,6 +110,7 @@
 {
   static gboolean print_version = FALSE;
   static gboolean be_verbose = FALSE;
+  static gboolean daemon = FALSE;
   static gchar *command;
   static const gchar *users_dir;
   static const gchar *config_file;
@@ -94,6 +124,8 @@
           "Print version.", NULL },
         { "verbose", 'v', 0, G_OPTION_ARG_NONE, &be_verbose,
           "Verbose messages.", NULL },
+        { "daemon", 'd', 0, G_OPTION_ARG_NONE, &daemon,
+          "Start in daemon mode.", NULL },
         { "command", 'c', 0, G_OPTION_ARG_STRING, &command,
           "OCP command", "<command>" },
         { "users-dir", 'u', 0, G_OPTION_ARG_FILENAME, &users_dir,
@@ -136,36 +168,168 @@
 
   if (command)
     {
+      GString *response = g_string_new(NULL);
+      g_strstrip(command);
       if (g_strcasecmp (command, "list_users") == 0)
         {
           GSList *user_list = openvas_config_list_users (users_dir);
-          if (user_list)
-            {
-              g_slist_foreach (user_list, print_user, NULL);
-            }
-          else
-            {
-              g_message ("Did not find any users in %s.", users_dir);
-            }
+          response = print_users_xml (user_list);
           g_slist_free (user_list);
         }
       else if (g_strcasecmp (command, "list_all_prefs") == 0)
         {
           GHashTable *all_prefs = openvas_config_list_all_prefs (config_file);
-          if (all_prefs)
+          response = print_preferences_xml (all_prefs);
+          g_hash_table_destroy (all_prefs);
+        }
+      else
+        {
+          g_string_printf (response, "<ocp_response command=\"%s\" status=\"500\" />", command);
+        }
+      g_printf ("%s\n", response->str);
+      g_string_free (response, TRUE);
+    }
+
+  if (daemon)
+    {
+      int socket_error, server_socket, i;
+      int client_socket, ret;
+      struct sockaddr_in sockaddr_server;
+      struct sockaddr_in sockaddr_client;
+      unsigned int client_len;
+      char client_info[512];
+      gnutls_session_t session;
+      char buffer[MAX_BUF + 1];
+      int optval = 1;
+      const int port = OPENVASCD_DEFAULT_PORT;
+
+      if (!g_file_test (OPENVAS_CA_CERTIFICATE, G_FILE_TEST_EXISTS) ||
+          !g_file_test (OPENVAS_SERVER_CERTIFICATE, G_FILE_TEST_EXISTS) ||
+          !g_file_test (OPENVAS_SERVER_KEY, G_FILE_TEST_EXISTS))
+        {
+          g_error ("Could not find certificate and key files needed to start the server (%s, %s, %s)",
+                   OPENVAS_CA_CERTIFICATE, OPENVAS_SERVER_CERTIFICATE, OPENVAS_SERVER_KEY);
+        }
+
+      if (gnutls_global_init () != 0)
+        {
+          g_error ("Failed to initialize GnuTLS global data.");
+        }
+
+      if (gnutls_certificate_allocate_credentials (&x509_cred) != 0)
+        {
+          g_error ("Failed to allocate GnuTLS certificate credentials.");
+        }
+
+      if (gnutls_certificate_set_x509_trust_file (x509_cred,
+                                                  OPENVAS_CA_CERTIFICATE,
+                                                  GNUTLS_X509_FMT_PEM) < 0)
+        {
+          g_error ("Failed to set the GnuTLS trust file (%s).", OPENVAS_CA_CERTIFICATE);
+        }
+
+      if (gnutls_certificate_set_x509_key_file (x509_cred,
+                                                OPENVAS_SERVER_CERTIFICATE,
+                                                OPENVAS_SERVER_KEY,
+                                                GNUTLS_X509_FMT_PEM) < 0)
+        {
+          g_error ("Failed to set the GnuTLS key file (%s, %s).",
+                   OPENVAS_SERVER_CERTIFICATE, OPENVAS_SERVER_KEY);
+        }
+
+      generate_dh_params ();
+
+      gnutls_certificate_set_dh_params (x509_cred, dh_params);
+
+      /* Socket operations */
+      server_socket = socket (AF_INET, SOCK_STREAM, 0);
+      SOCKET_ERR (server_socket, "socket");
+
+      memset (&sockaddr_server, '\0', sizeof (sockaddr_server));
+      sockaddr_server.sin_family = AF_INET;
+      sockaddr_server.sin_addr.s_addr = INADDR_ANY;
+      sockaddr_server.sin_port = htons (port);
+
+      setsockopt (server_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (int));
+
+      socket_error = bind (server_socket, (SA *) & sockaddr_server, sizeof (sockaddr_server));
+      SOCKET_ERR (socket_error, "bind");
+      socket_error = listen (server_socket, 1024);
+      SOCKET_ERR (socket_error, "listen");
+
+      g_debug ("Daemon setup finished, server ready. Listening to port '%d'.", port);
+
+      client_len = sizeof (sockaddr_client);
+      for (;;)
+        {
+          session = initialize_tls_session ();
+
+          client_socket = accept (server_socket, (SA *) & sockaddr_client, &client_len);
+
+          g_debug ("- connection from %s, port %d",
+                   inet_ntop (AF_INET, &sockaddr_client.sin_addr, client_info,
+                              sizeof (client_info)), ntohs (sockaddr_client.sin_port));
+
+          gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) client_socket);
+          ret = gnutls_handshake (session);
+          if (ret < 0)
             {
-              g_hash_table_foreach (all_prefs, print_preference, NULL);
-              g_hash_table_destroy (all_prefs);
+              close (client_socket);
+              gnutls_deinit (session);
+              g_message ("*** Handshake has failed (%s)", gnutls_strerror (ret));
+              continue;
             }
-          else
+          g_debug ("- Handshake was completed");
+
+          i = 0;
+          for (;;)
             {
-              g_message ("Could not find preferences in %s.", config_file);
+              memset (buffer, 0, MAX_BUF + 1);
+              ret = gnutls_record_recv (session, buffer, MAX_BUF);
+
+              if (ret == 0)
+                {
+                  g_debug ("- Peer has closed the GNUTLS connection");
+                  break;
+                }
+              else if (ret < 0)
+                {
+                  g_message ("*** Received corrupted data(%d)."
+                             " Closing the connection.", ret);
+                  break;
+                }
+              else if (ret > 0)
+                {
+                  GString *response = g_string_new(NULL);
+                  g_strstrip(buffer);
+                  if (g_strcasecmp (buffer, "list_users") == 0)
+                    {
+                      GSList *user_list = openvas_config_list_users (users_dir);
+                      response = print_users_xml (user_list);
+                      g_slist_free (user_list);
+                    }
+                  else if (g_strcasecmp (buffer, "list_all_prefs") == 0)
+                    {
+                      GHashTable *all_prefs = openvas_config_list_all_prefs (config_file);
+                      response = print_preferences_xml (all_prefs);
+                      g_hash_table_destroy (all_prefs);
+                    }
+                  else
+                    {
+                      g_string_printf (response,
+                                       "<ocp_response command=\"%s\" status=\"500\" />",
+                                       buffer);
+                    }
+                  gnutls_record_send (session, response->str, response->len);
+                  g_string_free (response, TRUE);
+                }
             }
+          close (client_socket);
+          gnutls_deinit (session);
         }
-      else
-        {
-          g_error ("The command %s is not supported.", command);
-        }
+      close (server_socket);
+      gnutls_certificate_free_credentials (x509_cred);
+      gnutls_global_deinit ();
     }
 
   exit (EXIT_SUCCESS);
@@ -272,3 +436,99 @@
       return NULL;
     }
 }
+
+/**
+ * @brief Produces an ocp_response element for a list_all_prefs request from a
+ * GHashTable of preferences.
+ *
+ * @param A pointer to a GHashTable containing preferences.
+ *
+ * @return A pointer to a GString containig the ocp_response element.
+ */
+GString *
+print_preferences_xml (GHashTable * preferences)
+{
+  GString *response = NULL;
+  if (preferences)
+    {
+      response = g_string_new ("<ocp_response command=\"list_all_prefs\" status=\"200\"><preferences>");
+      g_hash_table_foreach (preferences, print_preference, response);
+      response = g_string_append (response, "</preferences></ocp_response>");
+    }
+  else
+    {
+      response = g_string_new ("<ocp_response command=\"list_all_prefs\" status=\"200\"><preferences/></ocp_response>");
+    }
+  return response;
+}
+
+/**
+ * @brief Produces an ocp_response element for a list_users request from a
+ * GSList of users.
+ *
+ * @param A pointer to a GSList containing user names.
+ *
+ * @return A pointer to a GString containig the ocp_response element.
+ */
+GString *
+print_users_xml (GSList * users)
+{
+  GString *response = NULL;
+  if (users)
+    {
+      response = g_string_new ("<ocp_response command=\"list_users\" status=\"200\"><users>");
+      g_slist_foreach (users, print_user, response);
+      response = g_string_append (response, "</users></ocp_response>");
+    }
+  else
+    {
+      response = g_string_new ("<ocp_response command=\"list_users\" status=\"200\"><users/></ocp_response>");
+    }
+  return response;
+}
+
+/**
+ * @brief Initializes a GnuTLS session. Taken from the GnuTLS documentation.
+ *
+ * @return An initialized GnuTLS session.
+ */
+gnutls_session_t
+initialize_tls_session (void)
+{
+  gnutls_session_t session;
+
+  gnutls_init (&session, GNUTLS_SERVER);
+
+  /* avoid calling all the priority functions, since the defaults
+   * are adequate.
+   */
+  gnutls_set_default_priority (session);
+
+  gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+
+  /* request client certificate if any.
+   */
+  gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
+
+  gnutls_dh_set_prime_bits (session, DH_BITS);
+
+  return session;
+}
+
+/**
+ * @brief Generate Diffie Hellman parameters.
+ *
+ * Taken from the GnuTLS documentation, generates Diffie Hellman parameters
+ * for use with DHE kx algorithms. According to the GnuTLS documentation,
+ * these should be discarded and regenerated once a day, once a week or once a
+ * month, depending on the security requirements.
+ *
+ * \todo TODO: Implement parameter regeneration.
+ */
+static void
+generate_dh_params (void)
+{
+  gnutls_dh_params_init (&dh_params);
+  gnutls_dh_params_generate2 (dh_params, DH_BITS);
+  return;
+}



More information about the Openvas-commits mailing list