Sophie

Sophie

distrib > Mandriva > cs4.0 > i586 > by-pkgid > 815499440be9dbe5af8d2d488c9f855c > files > 2

openvpn-2.0.1-2.2.20060mdk.src.rpm

CVE-2005-3409

This patch will apply to OpenVPN 2.0.1 or 2.0.2 sources.

* Security fix -- Potential DoS vulnerability on the
  server in TCP mode.  If the TCP server accept() call
  returns an error status, the resulting exception handler
  may attempt to indirect through a NULL pointer, causing
  a segfault.  Affects all OpenVPN 2.0 versions.

Index: init.c
===================================================================
--- init.c	(revision 558)
+++ init.c	(working copy)
@@ -2350,7 +2350,7 @@
     else if (child)
       crypto_flags = CF_INIT_TLS_MULTI;
     do_init_crypto (c, crypto_flags);
-    if (IS_SIG (c))
+    if (IS_SIG (c) && !child)
       goto sig;
   }
 
@@ -2542,7 +2542,7 @@
   dest->c1.plugins = src->c1.plugins;
 
   /* context init */
-  init_instance (dest, src->c2.es, CC_USR1_TO_HUP | CC_GC_FREE);
+  init_instance (dest, src->c2.es, CC_NO_CLOSE | CC_USR1_TO_HUP);
   if (IS_SIG (dest))
     return;
 
@@ -2610,6 +2610,9 @@
 void
 close_context (struct context *c, int sig, unsigned int flags)
 {
+  ASSERT (c);
+  ASSERT (c->sig);
+
   if (sig >= 0)
     c->sig->signal_received = sig;
 
@@ -2620,7 +2623,8 @@
 	c->sig->signal_received = SIGHUP;
     }
 
-  close_instance (c);
+  if (!(flags & CC_NO_CLOSE))
+    close_instance (c);
 
   if (flags & CC_GC_FREE)
     context_gc_free (c);
Index: init.h
===================================================================
--- init.h	(revision 558)
+++ init.h	(working copy)
@@ -94,6 +94,8 @@
 #define CC_GC_FREE          (1<<0)
 #define CC_USR1_TO_HUP      (1<<1)
 #define CC_HARD_USR1_TO_HUP (1<<2)
+#define CC_NO_CLOSE         (1<<3)
+
 void close_context (struct context *c, int sig, unsigned int flags);
 
 struct context_buffers *init_context_buffers (const struct frame *frame);
Index: multi.c
===================================================================
--- multi.c	(revision 558)
+++ multi.c	(working copy)
@@ -405,7 +405,8 @@
 multi_client_disconnect_script (struct multi_context *m,
 				struct multi_instance *mi)
 {
-  if (mi->context.c2.context_auth == CAS_SUCCEEDED || mi->context.c2.context_auth == CAS_PARTIAL)
+  if ((mi->context.c2.context_auth == CAS_SUCCEEDED && mi->connection_established_flag)
+      || mi->context.c2.context_auth == CAS_PARTIAL)
     {
       multi_client_disconnect_setenv (m, mi);
 
@@ -569,10 +570,10 @@
       generate_prefix (mi);
     }
 
+  mi->did_open_context = true;
   inherit_context_child (&mi->context, &m->top);
   if (IS_SIG (&mi->context))
     goto err;
-  mi->did_open_context = true;
 
   mi->context.c2.context_auth = CAS_PENDING;
 
Index: openvpn.h
===================================================================
--- openvpn.h	(revision 558)
+++ openvpn.h	(working copy)
@@ -398,7 +398,7 @@
   in_addr_t push_ifconfig_local;
   in_addr_t push_ifconfig_remote_netmask;
 
-  /* client authentication state */
+  /* client authentication state, CAS_SUCCEEDED must be 0 */
 # define CAS_SUCCEEDED 0
 # define CAS_PENDING   1
 # define CAS_FAILED    2
Index: socket.c
===================================================================
--- socket.c	(revision 558)
+++ socket.c	(working copy)
@@ -1026,9 +1026,16 @@
   struct gc_arena gc = gc_new ();
   const char *remote_dynamic = NULL;
   bool remote_changed = false;
+  int sig_save = 0;
 
   ASSERT (sock);
 
+  if (signal_received && *signal_received)
+    {
+      sig_save = *signal_received;
+      *signal_received = 0;
+    }
+
   /* initialize buffers */
   socket_frame_init (frame, sock);
 
@@ -1220,6 +1227,11 @@
        print_sockaddr_ex (&sock->info.lsa->actual, addr_defined (&sock->info.lsa->actual), ":", &gc));
 
  done:
+  if (sig_save && signal_received)
+    {
+      if (!*signal_received)
+	*signal_received = sig_save;
+    }
   gc_free (&gc);
 }