[Openvas-commits] r3510 - in trunk/openvas-manager: . src src/tests

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Thu May 28 13:08:40 CEST 2009


Author: mattm
Date: 2009-05-28 13:08:39 +0200 (Thu, 28 May 2009)
New Revision: 3510

Added:
   trunk/openvas-manager/src/tests/read_protocol_0.c
Modified:
   trunk/openvas-manager/ChangeLog
   trunk/openvas-manager/src/openvasmd.c
   trunk/openvas-manager/src/tests/CMakeLists.txt
   trunk/openvas-manager/src/tests/common.c
   trunk/openvas-manager/src/tests/common.h
Log:
	Timeout if reading the protocol takes too long.

	* src/openvasmd.c (READ_PROTOCOL_TIMEOUT): New define.
	(protocol_read_t): Add PROTOCOL_TIMEOUT.
	(read_protocol): Timeout if reading takes PROTOCOL_TIMEOUT or longer.
	(serve_client): Handle read_protocol timeout.

	* src/tests/common.c (setup_test): New function.
	* src/tests/common.h (setup_test): New header.

	* src/tests/CMakeLists.txt: Add read_protocol_0.c.

	* src/tests/read_protocol_0.c: New file.

Modified: trunk/openvas-manager/ChangeLog
===================================================================
--- trunk/openvas-manager/ChangeLog	2009-05-28 10:53:01 UTC (rev 3509)
+++ trunk/openvas-manager/ChangeLog	2009-05-28 11:08:39 UTC (rev 3510)
@@ -1,3 +1,19 @@
+2009-05-28  Matthew Mundell <mmundell at intevation.de>
+
+	Timeout if reading the protocol takes too long.
+
+	* src/openvasmd.c (READ_PROTOCOL_TIMEOUT): New define.
+	(protocol_read_t): Add PROTOCOL_TIMEOUT.
+	(read_protocol): Timeout if reading takes PROTOCOL_TIMEOUT or longer.
+	(serve_client): Handle read_protocol timeout.
+
+	* src/tests/common.c (setup_test): New function.
+	* src/tests/common.h (setup_test): New header.
+
+	* src/tests/CMakeLists.txt: Add read_protocol_0.c.
+
+	* src/tests/read_protocol_0.c: New file.
+
 2009-05-27  Matthew Mundell <mmundell at intevation.de>
 
 	* src/omp.c (send_plugin): Correct g_convert charset names.

Modified: trunk/openvas-manager/src/openvasmd.c
===================================================================
--- trunk/openvas-manager/src/openvasmd.c	2009-05-28 10:53:01 UTC (rev 3509)
+++ trunk/openvas-manager/src/openvasmd.c	2009-05-28 11:08:39 UTC (rev 3510)
@@ -181,6 +181,13 @@
  */
 #define MAX_CONNECTIONS 512
 
+/**
+ * @brief Maximum number of seconds spent trying to read the protocol.
+ */
+#ifndef READ_PROTOCOL_TIMEOUT
+#define READ_PROTOCOL_TIMEOUT 20
+#endif
+
 #if FROM_BUFFER_SIZE > SSIZE_MAX
 #error FROM_BUFFER_SIZE too big for `read'
 #endif
@@ -215,7 +222,8 @@
   PROTOCOL_OTP,
   PROTOCOL_OMP,
   PROTOCOL_CLOSE,
-  PROTOCOL_FAIL
+  PROTOCOL_FAIL,
+  PROTOCOL_TIMEOUT
 } protocol_read_t;
 
 /**
@@ -266,11 +274,16 @@
  * @param[in]  client_session  The TLS session with the client.
  * @param[in]  client_socket   The socket connected to the client.
  *
- * @return PROTOCOL_FAIL, PROTOCOL_CLOSE, PROTOCOL_OTP or PROTOCOL_OMP.
+ * @return PROTOCOL_FAIL, PROTOCOL_CLOSE, PROTOCOL_OTP, PROTOCOL_OMP or
+ *         PROTOCOL_TIMEOUT.
  */
 protocol_read_t
 read_protocol (gnutls_session_t* client_session, int client_socket)
 {
+  protocol_read_t ret;
+  char* from_client_current;
+  time_t start_time;
+
   /* Turn on blocking. */
   // FIX get flags first
   if (fcntl (client_socket, F_SETFL, 0L) == -1)
@@ -280,76 +293,125 @@
     }
 
   /* Read from the client, checking the protocol when a newline or return
-   * is read. */
-  protocol_read_t ret = PROTOCOL_FAIL;
-  char* from_client_current = from_client + from_client_end;
+   * is read.  Fail if reading the protocol takes too long. */
+  if (time (&start_time) == -1)
+    {
+      perror ("Failed to get current time");
+      return PROTOCOL_FAIL;
+    }
+  ret = PROTOCOL_FAIL;
+  from_client_current = from_client + from_client_end;
   while (from_client_end < FROM_BUFFER_SIZE)
     {
-      ssize_t count;
+      int select_ret;
+      int nfds;
+      fd_set readfds, exceptfds;
+      struct timeval timeout;
 
-      while (1)
+      FD_ZERO (&readfds);
+      FD_SET (manager_socket, &readfds);
+      FD_ZERO (&exceptfds);
+      FD_SET (manager_socket, &exceptfds);
+      nfds = manager_socket + 1;
+
+      timeout.tv_usec = 0;
+      timeout.tv_sec = READ_PROTOCOL_TIMEOUT - (time (NULL) - start_time);
+      if (timeout.tv_sec <= 0)
         {
-          count = gnutls_record_recv (*client_session,
-                                      from_client + from_client_end,
-                                      FROM_BUFFER_SIZE
-                                      - from_client_end);
-          if (count == GNUTLS_E_INTERRUPTED)
-            /* Interrupted, try read again. */
-            continue;
-          if (count == GNUTLS_E_REHANDSHAKE)
-            /* Try again. TODO Rehandshake. */
-            continue;
+          ret = PROTOCOL_TIMEOUT;
           break;
         }
 
-      if (count < 0)
+      select_ret = select (nfds, &readfds, NULL, &exceptfds, &timeout);
+
+      if (select_ret == -1)
         {
-          if (gnutls_error_is_fatal (count) == 0
-              && (count == GNUTLS_E_WARNING_ALERT_RECEIVED
-                  || count == GNUTLS_E_FATAL_ALERT_RECEIVED))
-            {
-              int alert = gnutls_alert_get (*client_session);
-              fprintf (stderr, "TLS Alert %d: %s.\n",
-                       alert,
-                       gnutls_alert_get_name (alert));
-            }
-          fprintf (stderr, "Failed to read from client (read_protocol).\n");
-          gnutls_perror (count);
+          perror ("Select (read_protocol) failed");
           break;
         }
-      if (count == 0)
+      if (select_ret > 0)
         {
-          /* End of file. */
-          ret = PROTOCOL_CLOSE;
-          break;
-        }
-      from_client_end += count;
+          if (FD_ISSET (manager_socket, &exceptfds))
+            {
+              fprintf (stderr, "Exception in select.\n");
+              break;
+            }
+          if (FD_ISSET (manager_socket, &readfds))
+            {
+              ssize_t count;
 
+              while (1)
+                {
+
+                  count = gnutls_record_recv (*client_session,
+                                              from_client + from_client_end,
+                                              FROM_BUFFER_SIZE
+                                              - from_client_end);
+                  if (count == GNUTLS_E_INTERRUPTED)
+                    /* Interrupted, try read again. */
+                    continue;
+                  if (count == GNUTLS_E_REHANDSHAKE)
+                    /* Try again. TODO Rehandshake. */
+                    continue;
+                  break;
+                }
+
+              if (count < 0)
+                {
+                  if (gnutls_error_is_fatal (count) == 0
+                      && (count == GNUTLS_E_WARNING_ALERT_RECEIVED
+                          || count == GNUTLS_E_FATAL_ALERT_RECEIVED))
+                    {
+                      int alert = gnutls_alert_get (*client_session);
+                      fprintf (stderr, "TLS Alert %d: %s.\n",
+                               alert,
+                               gnutls_alert_get_name (alert));
+                    }
+                  fprintf (stderr, "Failed to read from client (read_protocol).\n");
+                  gnutls_perror (count);
+                  break;
+                }
+              if (count == 0)
+                {
+                  /* End of file. */
+                  ret = PROTOCOL_CLOSE;
+                  break;
+                }
+              from_client_end += count;
+
 #if 0
-      /* Check for newline or return. */
-      from_client[from_client_end] = '\0';
-      if (strchr (from_client_current, 10) || strchr (from_client_current, 13))
-        {
-          if (strstr (from_client, "< OTP/1.0 >"))
-            ret = PROTOCOL_OTP;
-          else
-            ret = PROTOCOL_OMP;
-          break;
+              /* Check for newline or return. */
+              from_client[from_client_end] = '\0';
+              if (strchr (from_client_current, 10) || strchr (from_client_current, 13))
+                {
+                  if (strstr (from_client, "< OTP/1.0 >"))
+                    ret = PROTOCOL_OTP;
+                  else
+                    ret = PROTOCOL_OMP;
+                  break;
+                }
+#else
+              /* Check for ">".  FIX need a better check */
+              from_client[from_client_end] = '\0';
+              if (strchr (from_client_current, '>'))
+                {
+                  if (strstr (from_client, "< OTP/1.0 >"))
+                    ret = PROTOCOL_OTP;
+                  else
+                    ret = PROTOCOL_OMP;
+                  break;
+                }
+#endif
+
+              from_client_current += count;
+            }
         }
-#else
-      /* Check for ">".  FIX need a better check */
-      from_client[from_client_end] = '\0';
-      if (strchr (from_client_current, '>'))
+
+      if ((time (NULL) - start_time) >= READ_PROTOCOL_TIMEOUT)
         {
-          if (strstr (from_client, "< OTP/1.0 >"))
-            ret = PROTOCOL_OTP;
-          else
-            ret = PROTOCOL_OMP;
+          ret = PROTOCOL_TIMEOUT;
           break;
         }
-#endif
-
-      from_client_current += count;
     }
 
   // FIX use orig value
@@ -439,6 +501,8 @@
       case PROTOCOL_CLOSE:
         fprintf (stderr, "EOF while trying to read protocol.\n");
         goto fail;
+      case PROTOCOL_TIMEOUT:
+        break;
       default:
         fprintf (stderr, "Failed to determine protocol.\n");
     }

Modified: trunk/openvas-manager/src/tests/CMakeLists.txt
===================================================================
--- trunk/openvas-manager/src/tests/CMakeLists.txt	2009-05-28 10:53:01 UTC (rev 3509)
+++ trunk/openvas-manager/src/tests/CMakeLists.txt	2009-05-28 11:08:39 UTC (rev 3510)
@@ -114,6 +114,15 @@
 set_target_properties (strip_space_3 PROPERTIES LINK_FLAGS "${GLIB_LDFLAGS}")
 ADD_TEST (strip_space_3 strip_space_3)
 
+## Tests of the manager
+
+add_executable (read_protocol_0 read_protocol_0.c)
+target_link_libraries (read_protocol_0 string)
+set_target_properties (read_protocol_0 PROPERTIES COMPILE_FLAGS "-I .. ${GLIB_CFLAGS}")
+set_target_properties (read_protocol_0 PROPERTIES LINK_FLAGS "${OVAS_LDFLAG} ${GLIB_LDFLAGS}")
+target_link_libraries (read_protocol_0 common)
+ADD_TEST (read_protocol_0 read_protocol_0)
+
 ## Tests of OMP
 
 add_executable (omp_abort_task_0 omp_abort_task_0.c)

Modified: trunk/openvas-manager/src/tests/common.c
===================================================================
--- trunk/openvas-manager/src/tests/common.c	2009-05-28 10:53:01 UTC (rev 3509)
+++ trunk/openvas-manager/src/tests/common.c	2009-05-28 11:08:39 UTC (rev 3510)
@@ -87,6 +87,7 @@
 #include <glib.h>             /* For XML parsing. */
 #include <netdb.h>
 #include <netinet/in.h>
+#include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -283,7 +284,7 @@
  * @param[in]  session  Pointer to GNUTLS session.
  * @param[in]  string   String to send.
  *
- * @return 0 on success, -1 on error.
+ * @return 0 on success, 1 if manager closed connection, -1 on error.
  */
 int
 send_to_manager (gnutls_session_t* session, const char* string)
@@ -294,6 +295,7 @@
       ssize_t count;
       tracef ("send %i from %.*s[...]\n", left, left < 30 ? left : 30, string);
       count = gnutls_record_send (*session, string, left);
+      tracef ("   count: %i\n", count);
       if (count < 0)
         {
           if (count == GNUTLS_E_INTERRUPTED)
@@ -309,6 +311,12 @@
           gnutls_perror (count);
           return -1;
         }
+      if (count == 0)
+        {
+          /* Manager closed connection. */
+          tracef ("=  manager closed\n");
+          return 1;
+        }
       tracef ("=> %.*s\n", count, string);
       string += count;
       left -= count;
@@ -324,7 +332,7 @@
  * @param[in]  session  Pointer to GNUTLS session.
  * @param[in]  format   printf-style format string for message.
  *
- * @return 0 on success, -1 on error.
+ * @return 0 on success, 1 if manager closed connection, -1 on error.
  */
 int
 sendf_to_manager (gnutls_session_t* session, const char* format, ...)
@@ -857,7 +865,7 @@
  * @param[in]  username  Username.
  * @param[in]  password  Password.
  *
- * @return 0 on success, -1 on error.
+ * @return 0 on success, 1 if manager closed connection, -1 on error.
  */
 int
 authenticate (gnutls_session_t* session,
@@ -872,7 +880,7 @@
                                 password);
   int ret = send_to_manager (session, msg);
   g_free (msg);
-  if (ret) return -1;
+  if (ret) return ret;
 
 #if 1
   return 0;
@@ -902,7 +910,7 @@
  *
  * @param[in]  session   Pointer to GNUTLS session.
  *
- * @return 0 on success, -1 on error.
+ * @return 0 on success, 1 if manager closed connection, -1 on error.
  */
 int
 env_authenticate (gnutls_session_t* session)
@@ -1312,3 +1320,14 @@
   if (first == '2') return 0;
   return -1;
 }
+
+
+/* Setup. */
+
+void
+setup_test ()
+{
+  char* env_verbose = getenv ("OPENVAS_TEST_VERBOSE");
+  if (env_verbose) verbose = strcmp (env_verbose, "0");
+  signal (SIGPIPE, SIG_IGN);
+}

Modified: trunk/openvas-manager/src/tests/common.h
===================================================================
--- trunk/openvas-manager/src/tests/common.h	2009-05-28 10:53:01 UTC (rev 3509)
+++ trunk/openvas-manager/src/tests/common.h	2009-05-28 11:08:39 UTC (rev 3510)
@@ -119,3 +119,8 @@
 
 int
 wait_for_task_start (gnutls_session_t*, char*);
+
+/* Setup. */
+
+void
+setup_test ();

Added: trunk/openvas-manager/src/tests/read_protocol_0.c
===================================================================
--- trunk/openvas-manager/src/tests/read_protocol_0.c	2009-05-28 10:53:01 UTC (rev 3509)
+++ trunk/openvas-manager/src/tests/read_protocol_0.c	2009-05-28 11:08:39 UTC (rev 3510)
@@ -0,0 +1,80 @@
+/* Test 0 of read_protocol.
+ * $Id$
+ * Description: Test read_protcol timing out.
+ *
+ * Authors:
+ * Matthew Mundell <matt at mundell.ukfsn.org>
+ *
+ * Copyright:
+ * Copyright (C) 2009 Greenbone Networks GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * or, at your option, any later version as published by the Free
+ * Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define TRACE 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "../tracef.h"
+
+int
+main ()
+{
+  int socket;
+  gnutls_session_t session;
+  char* id;
+
+  setup_test ();
+
+  socket = connect_to_manager (&session);
+  if (socket == -1) return EXIT_FAILURE;
+
+  /* FIX This must be more than the timeout, which is currently 20. */
+  sleep (25);
+
+  switch (env_authenticate (&session))
+    {
+      case 1:
+        /* Manager closed connection. */
+        close_manager_connection (socket, session);
+        return EXIT_SUCCESS;
+      default:
+        /* Authentication failed. */
+        break;
+    }
+
+  if (create_task_from_rc_file (&session,
+                                "new_task_small_rc",
+                                "Test for omp_delete_task_0",
+                                "Simple test scan.",
+                                &id))
+    {
+      close_manager_connection (socket, session);
+      return EXIT_SUCCESS;
+    }
+  entity_t entity = NULL;
+  if (read_entity (&session, &entity))
+    {
+      close_manager_connection (socket, session);
+      return EXIT_SUCCESS;
+    }
+
+  close_manager_connection (socket, session);
+  return EXIT_FAILURE;
+}



More information about the Openvas-commits mailing list