Fix duplicated PUSH_REPLY options
PATCH 1/1 Fix duplicated PUSH_REPLY options
Starting from https://github.com/OpenVPN/openvpn/commit/3a5a46cf2b7f6a8b8520c2513a8054deb48bfcbe,
we add peer-id and cipher values to context->options->push_list instead of adding those directly to buf (as done for client-specific values, like ifconfig). Since push_list is per child context, when options are added and context is reused - we got duplicates.
Fixed by adding options to buffer, as it was done previously.
--- src/openvpn/push.c | 83 +++++++++++++++--------------------------------------- 1 file changed, 22 insertions(+), 61 deletions(-)
src/openvpn/push.c +22 -61
@@ -40,30 +40,6 @@#if P2MP -/** -* Add an option to the push list by providing a format string. -* -* The string added to the push options is allocated in o->gc, so the caller -* does not have to preserve anything. -* -* @param o The current connection's options -* @param msglevel The message level to use when printing errors -* @param fmt Format string for the option -* @param ... Format string arguments -* -* @return true on success, false on failure. -*/ -static bool push_option_fmt (struct options *o,int msglevel, - const char *fmt, ...) -#ifdef __GNUC__ -#if __USE_MINGW_ANSI_STDIO - __attribute__ ((format (gnu_printf, 3, 4))) -#else - __attribute__ ((format (__printf__, 3, 4))) -#endif -#endif - ; -/* * Auth username/password *
@@ -293,31 +269,31 @@ send_push_request (struct context *c)#if P2MP_SERVER /** -* Prepare push options, based on local options and available peer info. +* Add peer specific options, based on local options and peer info. * -* @param options Connection options * @param tls_multi TLS state structure for the current tunnel +* @param options Connection options +* @param buf buffer to where options are added * -* @return true on success, false on failure. */ -static bool -prepare_push_reply (struct options *o,struct tls_multi *tls_multi) +static void +add_peer_specific_opts (struct tls_multi *tls_multi,struct options *o,struct buffer *buf) { -const char *optstr =NULL ;const char *const peer_info = tls_multi->peer_info; - +const char *optstr =NULL ; +/* Send peer-id if client supports it */ - optstr = peer_info ?strstr (peer_info,"IV_PROTO=" ) :NULL ; + optstr = peer_info ?strstr (peer_info,"IV_PROTO=" ) :NULL ;if (optstr) - { -int proto =0 ; -int r =sscanf (optstr,"IV_PROTO=%d" , &proto); -if ((r ==1 ) && (proto >=2 )) - { -push_option_fmt (o,M_USAGE ,"peer-id %d" , tls_multi->peer_id); - } - } - + { +int proto =0 ; +int r =sscanf (optstr,"IV_PROTO=%d" , &proto); +if ((r ==1 ) && (proto >=2 )) + { +buf_printf (buf,",peer-id %d" , tls_multi->peer_id); + } + } +/* Push cipher if client supports Negotiable Crypto Parameters */ if (tls_peer_info_ncp_ver (peer_info) >=2 && o->ncp_enabled) {
@@ -335,12 +311,11 @@ prepare_push_reply (struct options *o, struct tls_multi *tls_multi) {/* Push the first cipher from --ncp-ciphers to the client. * TODO: actual negotiation, instead of server dictatorship. */ -char *push_cipher =string_alloc (o->ncp_ciphers, &o->gc); +char *push_cipher =string_alloc (o->ncp_ciphers, &o->gc); o->ciphername =strtok (push_cipher,":" ); -push_option_fmt (o,M_USAGE ,"cipher %s" , o->ciphername); +buf_printf (buf,",cipher %s" , o->ciphername); } } -return true; } static bool
@@ -414,6 +389,8 @@ send_push_reply (struct context *c)if (multi_push)buf_printf (&buf,",push-continuation 1" ); +add_peer_specific_opts (c->c2.tls_multi, &c->options, &buf); +if (BLEN (&buf) >sizeof (cmd)-1 ) {const bool status =send_control_channel_string (c,BSTR (&buf),D_PUSH );
@@ -501,21 +478,6 @@ push_options (struct options *o, char **p, int msglevel, struct gc_arena *gc)push_option (o, opt, msglevel); } -static bool push_option_fmt (struct options *o,int msglevel, -const char *format, ...) -{ -va_list arglist; -char tmp[256 ] = {0 }; -int len =-1 ; -va_start (arglist, format); - len =vsnprintf (tmp,sizeof (tmp), format, arglist); -va_end (arglist); -if (len >sizeof (tmp)-1 ) -return false; -push_option (o,string_alloc (tmp, &o->gc), msglevel); -return true; -} -void push_reset (struct options *o) {
@@ -580,8 +542,7 @@ process_incoming_push_request (struct context *c) }else { -if (prepare_push_reply (&c->options, c->c2.tls_multi) && -send_push_reply (c)) +if (send_push_reply (c)) { ret =PUSH_MSG_REQUEST ; c->c2.sent_push_reply_expiry = now +30 ;
Signature · 1 line
1.9.1
Hi,
Quoted 6 lines · Lev Stipakov
Starting from https://github.com/OpenVPN/openvpn/commit/3a5a46cf2b7f6a8b8520c2513a8054deb48bfcbe,
we add peer-id and cipher values tocontext->options->push_listinstead of adding those directly to buf (as done for client-specific values, like ifconfig). Sincepush_listis per child context, when options are added and context is reused - we got duplicates.Fixed by adding options to buffer, as it was done previously.
NAK. This reintroduces another issue, where the added options might not fit into buf, because we can't reserve space for variable-sized options (peer-id would be possible, by cipher would already be trickier).
This is a bug though (sorry!), so attached a different proposal to fix this. I didn't test this yet (need to leave now), but lev just announced on IRC that he was willing to test it.
-Steffan
From 957c54a7f4cefdc05e5e876195ef31a52c00f2b3 Mon Sep 17 00:00:00 2001
From: Steffan Karger <[email protected]>
Date: Thu, 29 Sep 2016 19:48:29 +0200
Subject: [PATCH] Fix duplicate PUSH_REPLY options
As reported by Lev Stipakov, starting from 3a5a46cf we add peer-id and cipher values to context->options->push_list instead of adding those directly to buf. Since push_list is preserved over sigusr1 restarts, we add duplicate values for peer-id and cipher.
Fixed by removing the previous values from the list before adding new ones.
--- src/openvpn/errlevel.h | 1 + src/openvpn/options.c | 1 + src/openvpn/push.c | 6 ++++-- 3 files changed, 6 insertions(+), 2 deletions(-)
src/openvpn/errlevel.h +1 -0
@@ -147,6 +147,7 @@#define D_PID_DEBUG LOGLEV(7, 70, M_DEBUG)/* show packet-id debugging info */ #define D_PF_DROPPED_BCAST LOGLEV(7, 71, M_DEBUG)/* packet filter dropped a broadcast packet */ #define D_PF_DEBUG LOGLEV(7, 72, M_DEBUG)/* packet filter debugging, must also define PF_DEBUG in pf.h */ +#define D_PUSH_DEBUG LOGLEV(7, 73, M_DEBUG)/* show push/pull debugging info */ #define D_HANDSHAKE_VERBOSE LOGLEV(8, 70, M_DEBUG)/* show detailed description of each handshake */ #define D_TLS_DEBUG_MED LOGLEV(8, 70, M_DEBUG)/* limited info from tls_session routines */
src/openvpn/options.c +1 -0
@@ -5781,6 +5781,7 @@ add_option (struct options *options,else if (streq (p[0 ],"push-remove" ) && p[1 ] && !p[2 ]) {VERIFY_PERMISSION (OPT_P_INSTANCE ); +msg (D_PUSH ,"PUSH_REMOVE '%s'" , p[1 ]);push_remove_option (options,p[1 ]); }else if (streq (p[0 ],"ifconfig-pool" ) && p[1 ] && p[2 ] && !p[4 ])
src/openvpn/push.c +4 -2
@@ -314,6 +314,7 @@ prepare_push_reply (struct options *o, struct tls_multi *tls_multi)int r =sscanf (optstr,"IV_PROTO=%d" , &proto);if ((r ==1 ) && (proto >=2 )) { +push_remove_option (o,"peer-id" );push_option_fmt (o,M_USAGE ,"peer-id %d" , tls_multi->peer_id); } }
@@ -337,6 +338,7 @@ prepare_push_reply (struct options *o, struct tls_multi *tls_multi)* TODO: actual negotiation, instead of server dictatorship. */ char *push_cipher =string_alloc (o->ncp_ciphers, &o->gc); o->ciphername =strtok (push_cipher,":" ); +push_remove_option (o,"cipher" );push_option_fmt (o,M_USAGE ,"cipher %s" , o->ciphername); } }
@@ -525,7 +527,7 @@ push_reset (struct options *o)void push_remove_option (struct options *o,const char *p) { -msg (D_PUSH ,"PUSH_REMOVE '%s'" , p ); +msg (D_PUSH_DEBUG ,"PUSH_REMOVE searching for: '%s'" , p);/* ifconfig-ipv6 is special, as not part of the push list */ if (streq ( p,"ifconfig-ipv6" ))
@@ -544,7 +546,7 @@ push_remove_option (struct options *o, const char *p)if ( e->enable &&strncmp ( e->option, p,strlen (p) ) ==0 ) { -msg (D_PUSH ,"PUSH_REMOVE removing: '%s'" , e->option); +msg (D_PUSH_DEBUG ,"PUSH_REMOVE removing: '%s'" , e->option); e->enable = false; }
Signature · 1 line
2.7.4
Hi,
ACK from me - tested that peer-id and cipher are not duplicated in PUSH_REPLY when client reconnects and push-continuation works.
-Lev
2016-09-29 20:49 GMT+03:00 Steffan Karger <[email protected]...>:
Quoted 24 lines
Hi,
Quoted 1 line · Lev Stipakov
Starting from https://github.com/OpenVPN/openvpn/commit/
3a5a46cf2b7f6a8b8520c2513a8054deb48bfcbe,Quoted 1 line
we add peer-id and cipher values to
context->options->push_listinsteadof adding those directly
Quoted 1 line
to buf (as done for client-specific values, like ifconfig). Since
push_listis per child context,Quoted 3 lines
when options are added and context is reused - we got duplicates.
Fixed by adding options to buffer, as it was done previously.
NAK. This reintroduces another issue, where the added options might not fit into buf, because we can't reserve space for variable-sized options (peer-id would be possible, by cipher would already be trickier).
This is a bug though (sorry!), so attached a different proposal to fix this. I didn't test this yet (need to leave now), but lev just announced on IRC that he was willing to test it.
-Steffan
Signature · 1 line
-Lev
PATCH 1/1 Fix duplicated PUSH_REPLY options
In reply to Steffan KargerHi,
Attempt #2 - now with attached patch.
ACK from me - tested that peer-id and cipher are not duplicated in PUSH_REPLY when client reconnects and push-continuation works.
-Lev
---------- Forwarded message ----------
From: Steffan Karger <[email protected]...>
Date: 2016-09-29 20:49 GMT+03:00
Subject: Re: [Openvpn-devel] [PATCH] Fix duplicated PUSH_REPLY options
To: Lev Stipakov <[email protected]...>
Hi,
Quoted 1 line · Lev Stipakov
Starting from https://github.com/OpenVPN/openvpn/commit/3a5a46cf2b7f6a8b85
20c2513a8054deb48bfcbe,
Quoted 1 line
we add peer-id and cipher values to
context->options->push_listinstead
of adding those directly
Quoted 1 line
to buf (as done for client-specific values, like ifconfig). Since
push_list is per child context,
Quoted 3 lines
when options are added and context is reused - we got duplicates.
Fixed by adding options to buffer, as it was done previously.
NAK. This reintroduces another issue, where the added options might not fit into buf, because we can't reserve space for variable-sized options (peer-id would be possible, by cipher would already be trickier).
This is a bug though (sorry!), so attached a different proposal to fix this. I didn't test this yet (need to leave now), but lev just announced on IRC that he was willing to test it.
-Steffan
Signature · 1 line
-Lev
From 957c54a7f4cefdc05e5e876195ef31a52c00f2b3 Mon Sep 17 00:00:00 2001
From: Steffan Karger <[email protected]>
Date: Thu, 29 Sep 2016 19:48:29 +0200
Subject: [PATCH] Fix duplicate PUSH_REPLY options
As reported by Lev Stipakov, starting from 3a5a46cf we add peer-id and cipher values to context->options->push_list instead of adding those directly to buf. Since push_list is preserved over sigusr1 restarts, we add duplicate values for peer-id and cipher.
Fixed by removing the previous values from the list before adding new ones.
--- src/openvpn/errlevel.h | 1 + src/openvpn/options.c | 1 + src/openvpn/push.c | 6 ++++-- 3 files changed, 6 insertions(+), 2 deletions(-)
src/openvpn/errlevel.h +1 -0
@@ -147,6 +147,7 @@#define D_PID_DEBUG LOGLEV(7, 70, M_DEBUG)/* show packet-id debugging info */ #define D_PF_DROPPED_BCAST LOGLEV(7, 71, M_DEBUG)/* packet filter dropped a broadcast packet */ #define D_PF_DEBUG LOGLEV(7, 72, M_DEBUG)/* packet filter debugging, must also define PF_DEBUG in pf.h */ +#define D_PUSH_DEBUG LOGLEV(7, 73, M_DEBUG)/* show push/pull debugging info */ #define D_HANDSHAKE_VERBOSE LOGLEV(8, 70, M_DEBUG)/* show detailed description of each handshake */ #define D_TLS_DEBUG_MED LOGLEV(8, 70, M_DEBUG)/* limited info from tls_session routines */
src/openvpn/options.c +1 -0
@@ -5781,6 +5781,7 @@ add_option (struct options *options,else if (streq (p[0 ],"push-remove" ) && p[1 ] && !p[2 ]) {VERIFY_PERMISSION (OPT_P_INSTANCE ); +msg (D_PUSH ,"PUSH_REMOVE '%s'" , p[1 ]);push_remove_option (options,p[1 ]); }else if (streq (p[0 ],"ifconfig-pool" ) && p[1 ] && p[2 ] && !p[4 ])
src/openvpn/push.c +4 -2
@@ -314,6 +314,7 @@ prepare_push_reply (struct options *o, struct tls_multi *tls_multi)int r =sscanf (optstr,"IV_PROTO=%d" , &proto);if ((r ==1 ) && (proto >=2 )) { +push_remove_option (o,"peer-id" );push_option_fmt (o,M_USAGE ,"peer-id %d" , tls_multi->peer_id); } }
@@ -337,6 +338,7 @@ prepare_push_reply (struct options *o, struct tls_multi *tls_multi)* TODO: actual negotiation, instead of server dictatorship. */ char *push_cipher =string_alloc (o->ncp_ciphers, &o->gc); o->ciphername =strtok (push_cipher,":" ); +push_remove_option (o,"cipher" );push_option_fmt (o,M_USAGE ,"cipher %s" , o->ciphername); } }
@@ -525,7 +527,7 @@ push_reset (struct options *o)void push_remove_option (struct options *o,const char *p) { -msg (D_PUSH ,"PUSH_REMOVE '%s'" , p ); +msg (D_PUSH_DEBUG ,"PUSH_REMOVE searching for: '%s'" , p);/* ifconfig-ipv6 is special, as not part of the push list */ if (streq ( p,"ifconfig-ipv6" ))
@@ -544,7 +546,7 @@ push_remove_option (struct options *o, const char *p)if ( e->enable &&strncmp ( e->option, p,strlen (p) ) ==0 ) { -msg (D_PUSH ,"PUSH_REMOVE removing: '%s'" , e->option); +msg (D_PUSH_DEBUG ,"PUSH_REMOVE removing: '%s'" , e->option); e->enable = false; }
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [PATCH applied] Fix duplicate PUSH_REPLY options
In reply to Steffan KargerThanks.
Your patch has been applied to the master branch
commit 974ec19daa6c9d4e954912b3743c7101637f1d33
Author: Steffan Karger Date: Thu Sep 29 19:48:29 2016 +0200
Fix duplicate PUSH_REPLY options
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Lev Stipakov <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/[email protected]/msg12642.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering