[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