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); }