Hello,

I have just added a new change request regarding HTTP/HTTPS proxy support in 
openvas-libraries (http://www.openvas.org/openvas-cr-51.html).

I'd like to thank Christian Kuersteiner for the idea behind this change 
request and for providing a working prototype as well. I've attached the 
patch to this mail; please note that the control infrastructure contained in 
the patch is not yet final and the patch currently only supports proxies on 
localhost. This will of course change in the final version.

Please let me or Christian know if you have any questions or suggestions 
regarding this feature.

Regards,

Michael

-- 
Michael Wiegand |  Greenbone Networks GmbH  |  http://www.greenbone.net/
Neuer Graben 17, 49074 Osnabrück, Germany | AG Osnabrück, HR B 202460
Executive Directors: Lukas Grunwald, Dr. Jan-Oliver Wagner

Index: nasl/nasl_socket.c
===================================================================
--- nasl/nasl_socket.c	(Revision 9388)
+++ nasl/nasl_socket.c	(Arbeitskopie)
@@ -390,7 +390,67 @@
   return retc;
 }
 
+/*
+ * @brief Open a socket through a proxy.
+ *
+ * This function is more or less the same as the open_sock_tcp() function but
+ * connects to the proxy instead of directly to the target.
+ *
+ * @param[in] lexic The parser context.
+ *
+ * @return A tree_cell containing the socket or NULL if no proxy was set.
+ */
 tree_cell *
+nasl_open_sock_proxy (lex_ctxt * lexic)
+{
+  int soc = -1;
+  struct arglist *script_infos = lexic->script_infos;
+  int to, port, transport = -1;
+  tree_cell *retc;
+  int bufsz = 65536;
+  struct kb_item **kb;
+
+  to = get_int_local_var_by_name (lexic, "timeout", lexic->recv_timeout * 2);
+  if (to < 0)
+    to = 10;
+
+  transport = get_int_local_var_by_name (lexic, "transport", -1);
+
+  /* Connect to the proxy port instead the target port */
+  kb = plug_get_kb (script_infos);
+  port = kb_item_get_int (kb, "Proxy/port");
+  if (port < 0)
+    {
+      return NULL;
+    }
+
+  if (transport < 0)
+    {
+      soc = open_stream_auto_encaps_proxy (script_infos, port, to);
+    }
+  else
+    {
+      soc = open_stream_connection_proxy (script_infos, port, transport, to);
+    }
+
+  if (soc >= 0)
+    {
+      if (stream_set_buffer (soc, bufsz) < 0)
+        {
+          nasl_perror (lexic, "stream_set_buffer: soc=%d,bufsz=%d\n", soc,
+                       bufsz);
+        }
+    }
+
+  /* return the socket in a tree_cell */
+  retc = alloc_tree_cell (0, NULL);
+  retc->type = CONST_INT;
+  retc->x.i_val = soc < 0 ? 0 : soc;
+
+  return retc;
+}
+
+tree_cell *
 nasl_open_sock_tcp (lex_ctxt * lexic)
 {
   return nasl_open_sock_tcp_bufsz (lexic, -1);
Index: nasl/nasl_socket.h
===================================================================
--- nasl/nasl_socket.h	(Revision 9388)
+++ nasl/nasl_socket.h	(Arbeitskopie)
@@ -33,6 +33,7 @@
 tree_cell *nasl_open_sock_udp (lex_ctxt *);
 /* private func */
 tree_cell *nasl_open_sock_tcp_bufsz (lex_ctxt *, int);
+tree_cell *nasl_open_sock_proxy (lex_ctxt *);
 tree_cell *nasl_socket_get_error (lex_ctxt *);
 
 tree_cell *nasl_open_priv_sock_tcp (lex_ctxt *);
Index: nasl/nasl_http.c
===================================================================
--- nasl/nasl_http.c	(Revision 9388)
+++ nasl/nasl_http.c	(Arbeitskopie)
@@ -47,10 +47,35 @@
 
 
 
+/**
+ * @brief Opens a socket for HTTP.
+ *
+ * Opens a socket for HTTP connection either direct to the target or
+ * if specified to a proxy.
+ *
+ * @param[in] lexic The parser context.
+ *
+ * @return A tree cell containing the socket for the connection.
+ */
 tree_cell *
 http_open_socket (lex_ctxt * lexic)
 {
-  return nasl_open_sock_tcp_bufsz (lexic, 65536);
+  struct arglist *script_infos = lexic->script_infos;
+  struct kb_item **kb;
+  int useproxy;
+
+  /* Check if we are using a proxy */
+  kb = plug_get_kb (script_infos);
+  useproxy = kb_item_get_int (kb, "Proxy/use_proxy");
+
+  if (useproxy != 0)
+    {
+      /* Connect to the proxy instead to the target */
+      return nasl_open_sock_proxy (lexic);
+    }
+  else
+    /* Connect direct to the target */
+    return nasl_open_sock_tcp_bufsz (lexic, 65536);
 }
 
 tree_cell *
@@ -77,6 +102,8 @@
   char content_l_str[32];
   struct kb_item **kb;
   int str_length = 0;
+  int useproxy;
+  char *host;
 
 
   if (item == NULL || port < 0)
@@ -156,6 +183,14 @@
     }
   else
     {
+      /* Use Proxy */
+      useproxy = kb_item_get_int (kb, "Proxy/use_proxy");
+      if (useproxy != 0)
+        {
+          host = (char *) plug_get_host_fqdn (script_infos);
+          item = g_strconcat ("http://";, host, item, NULL);
+        }
+
       /* NIDS evasion */
       url =
         build_encode_URL (script_infos, keyword, NULL, item, "HTTP/1.0\r\n");
Index: ChangeLog
===================================================================
--- ChangeLog	(Revision 9388)
+++ ChangeLog	(Arbeitskopie)
@@ -1,3 +1,21 @@
+2010-11-11  Michael Wiegand <michael.wieg...@greenbone.net>
+
+	* nasl/nasl_http.c (http_open_socket): Use proxy instead of connection
+	directly to the target if requested.
+	(_http_req): Use proxy if requested.
+
+	* nasl/nasl_socket.c (nasl_open_sock_proxy): New function for
+	connecting to a proxy instead of directly to the target.
+
+	* nasl/nasl_socket.h: Updated.
+
+	* misc/network.c (open_sock_option_proxy, open_sock_proxy)
+	(open_stream_connection_proxy, open_stream_auto_encaps_proxy)
+	(open_stream_connection_unknown_encaps5_proxy): New functions to
+	open connections through a proxy.
+
+	* misc/network.h: Updated.
+
 2010-11-09  Jan-Oliver Wagner <jan-oliver.wag...@greenbone.net>
 
 	* misc/CMakeLists.txt: Changed install directory for headers
Index: misc/network.c
===================================================================
--- misc/network.c	(Revision 9388)
+++ misc/network.c	(Arbeitskopie)
@@ -26,6 +26,7 @@
  */
 
 #include <sys/types.h>
+#include <arpa/inet.h>
 #include <unistd.h>
 #include <stdarg.h>
 #include <string.h>
@@ -2831,3 +2832,262 @@
     return gnutls_record_check_pending (fp->tls_session);
   return 0;
 }
+
+
+/**
+ * @brief Open a socket with options through a proxy.
+ *
+ * @param[in] args Arglist containing the context.
+ * @param[in] port Port to connect to.
+ * @param[in] type Type of socket.
+ * @param[in] protocol Protocol to used with the socket.
+ * @param[in] timeout Timeout for connection.
+ *
+ * @return Socket for this connection.
+ */
+int
+open_sock_option_proxy (struct arglist *args, unsigned int port, int type,
+                        int protocol, int timeout)
+{
+  struct sockaddr_in addr;
+
+  bzero ((void *) &addr, sizeof (addr));
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons ((unsigned short) port);
+  addr.sin_addr.s_addr = inet_addr ("127.0.0.1"); // @TODO: ???
+  return open_socket ((struct sockaddr *) &addr, port, type, protocol, timeout,
+                      sizeof (struct sockaddr_in));
+}
+
+/**
+ * @brief Open a socket through a proxy.
+ *
+ * @param[in] args Arglist containing the context.
+ * @param[in] port Port to connect to.
+ * @param[in] timeout Timeout for connection.
+ *
+ * @return Socket for this connection.
+ */
+int
+open_sock_proxy (struct arglist *args, unsigned int port, int timeout)
+{
+  char name[32];
+  int ret;
+  int type;
+
+  /* If we timed out against this port in the past, there's no need
+   * to scan it again */
+  snprintf (name, sizeof (name), "/tmp/ConnectTimeout/TCP/%d", port);   /* RATS: ignore */
+  if (plug_get_key (args, name, &type))
+    return -1;
+
+  errno = 0;
+  ret = open_sock_option_proxy (args, port, SOCK_STREAM, IPPROTO_TCP, timeout);
+  if (ret < 0 && errno == ETIMEDOUT)
+    plug_set_key (args, name, ARG_INT, (void *) 1);
+
+  return ret;
+}
+
+
+/**
+ * @brief Open a stream connection through a proxy.
+ *
+ * @param[in] args Arglist containing the context.
+ * @param[in] port Port to connect to.
+ * @param[in] transport Transport layer code.
+ * @param[in] timeout Timeout for connection.
+ *
+ * @return Newly created socket for this connection.
+ */
+int
+open_stream_connection_proxy (struct arglist *args, unsigned int port,
+                              int transport, int timeout)
+{
+  int fd;
+  openvas_connection *fp;
+  char *cert = NULL;
+  char *key = NULL;
+  char *passwd = NULL;
+  char *cafile = NULL;
+
+#if DEBUG_SSL > 2
+  fprintf (stderr,
+           "[%d] open_stream_connection_proxy: TCP:%d transport:%d timeout:%d\n",
+           getpid (), port, transport, timeout);
+#endif
+
+  if (timeout == -2)
+    timeout = TIMEOUT;
+
+  switch (transport)
+    {
+    case OPENVAS_ENCAPS_IP:
+    case OPENVAS_ENCAPS_SSLv23:
+    case OPENVAS_ENCAPS_SSLv3:
+    case OPENVAS_ENCAPS_TLSv1:
+      break;
+
+    case OPENVAS_ENCAPS_SSLv2:
+    default:
+      fprintf (stderr,
+               "open_stream_connection_proxy(): unsupported transport layer %d\n",
+               transport);
+      errno = EINVAL;
+      return -1;
+    }
+
+  if ((fd = get_connection_fd ()) < 0)
+    return -1;
+
+  fp = &(connections[fd - OPENVAS_FD_OFF]);
+
+
+  fp->transport = transport;
+  fp->timeout = timeout;
+  fp->port = port;
+  fp->last_err = 0;
+  set_ids_evasion_mode (args, fp);
+
+  // @TODO: No proxy if OPENVAS_CNX_IDS_EVASION_FAKE_RST is set?
+  if (fp->options & OPENVAS_CNX_IDS_EVASION_FAKE_RST)
+    fp->fd = ids_open_sock_tcp (args, port, fp->options, timeout);
+  else
+    fp->fd = open_sock_proxy (args, port, timeout);
+
+  if (fp->fd < 0)
+    goto failed;
+
+  switch (transport)
+    {
+    case OPENVAS_ENCAPS_IP:
+      break;
+    case OPENVAS_ENCAPS_SSLv23:
+    case OPENVAS_ENCAPS_SSLv3:
+    case OPENVAS_ENCAPS_TLSv1:
+      renice_myself ();
+      cert = kb_item_get_str (plug_get_kb (args), "SSL/cert");
+      key = kb_item_get_str (plug_get_kb (args), "SSL/key");
+      passwd = kb_item_get_str (plug_get_kb (args), "SSL/password");
+      cafile = kb_item_get_str (plug_get_kb (args), "SSL/CA");
+
+      /* fall through */
+    case OPENVAS_ENCAPS_SSLv2:
+      /* We do not need a client certificate in this case */
+      if (open_SSL_connection (fp, timeout, cert, key, passwd, cafile) <= 0)
+        goto failed;
+      break;
+    }
+
+  return fd;
+
+failed:
+  release_connection_fd (fd);
+  return -1;
+}
+
+/**
+ * @brief Open a stream connection with unknown encapsulation through a proxy.
+ *
+ * @param[in] args Arglist containing the context.
+ * @param[in] port Port to connect to.
+ * @param[in] timeout Timeout for connection.
+ * @param[out] p The encapsulation which was found to be working.
+ * @param[out] delta_t If set, the time it took to open the connection in
+ * microseconds.
+ *
+ * @return Newly created socket for this connection.
+ */
+int
+open_stream_connection_unknown_encaps5_proxy (struct arglist *args,
+                                              unsigned int port, int timeout,
+                                              int *p, int *delta_t)
+{
+  int fd;
+  int i;
+  struct timeval tv1, tv2;
+  static int encaps[] = {
+    OPENVAS_ENCAPS_SSLv2,
+    OPENVAS_ENCAPS_TLSv1,
+    OPENVAS_ENCAPS_SSLv3,
+    OPENVAS_ENCAPS_IP
+  };
+
+#if DEBUG_SSL > 2
+  fprintf (stderr,
+           "[%d] open_stream_connection_unknown_encaps5_proxy: TCP:%d; %d\n",
+           getpid (), port, timeout);
+#endif
+
+  for (i = 0; i < sizeof (encaps) / sizeof (*encaps); i++)
+    {
+      if (delta_t != NULL)
+        {
+          (void) gettimeofday (&tv1, NULL);
+        }
+      if ((fd =
+           open_stream_connection_proxy (args, port, encaps[i], timeout)) >= 0)
+        {
+          *p = encaps[i];
+#if DEBUG_SSL > 2
+          fprintf (stderr,
+                   "[%d] open_stream_connection_unknown_encaps5_proxy: TCP:%d -> transport=%d\n",
+                   getpid (), port, *p);
+#endif
+          if (delta_t != NULL)
+            {
+              (void) gettimeofday (&tv2, NULL);
+              *delta_t =
+                (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec -
+                                                       tv1.tv_usec);
+            }
+          return fd;
+        }
+      else if (__port_closed)
+        {
+#if DEBUG_SSL > 2
+          fprintf (stderr,
+                   "[%d] open_stream_connection_unknown_encaps5_proxy: TCP:%d -> closed\n",
+                   getpid (), port);
+#endif
+          return -1;
+        }
+    }
+  return -1;
+}
+
+
+/**
+ * @brief Open a stream connection through a proxy with automatic setting of the
+ * necessary encapsulation.
+ *
+ * @param[in] args Arglist containing the context.
+ * @param[in] port Proxy port to connect to.
+ * @param[in] timeout Timeout for the socket creation.
+ *
+ * @return Newly created socket for this connection.
+ */
+int
+open_stream_auto_encaps_proxy (struct arglist *args, unsigned int port,
+                               int timeout)
+{
+  int trp = plug_get_port_transport (args, port);
+  int fd;
+
+  if (trp == 0)
+    {
+      if ((fd =
+           open_stream_connection_unknown_encaps5_proxy (args, port, timeout,
+                                                         &trp, NULL)) < 0)
+        {
+          return -1;
+        }
+      plug_set_port_transport (args, port, trp);
+      return fd;
+    }
+  else
+    {
+      fd = open_stream_connection_proxy (args, port, trp, timeout);
+      return fd;
+    }
+ /*NOTREACHED*/}
Index: misc/network.h
===================================================================
--- misc/network.h	(Revision 9388)
+++ misc/network.h	(Arbeitskopie)
@@ -43,6 +43,7 @@
 int socket_close (int);
 
 int open_stream_connection (struct arglist *, unsigned int, int, int);
+int open_stream_connection_proxy (struct arglist *, unsigned int, int, int);
 int open_stream_connection_unknown_encaps (struct arglist *, unsigned int, int,
                                            int *);
 int open_stream_connection_unknown_encaps5 (struct arglist *, unsigned int, int,
_______________________________________________
Openvas-devel mailing list
Openvas-devel@wald.intevation.org
http://lists.wald.intevation.org/mailman/listinfo/openvas-devel

Reply via email to