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. Signed-off-by: Lev Stipakov <lstipa...@gmail.com> --- src/openvpn/push.c | 83 +++++++++++++++--------------------------------------- 1 file changed, 22 insertions(+), 61 deletions(-) diff --git a/src/openvpn/push.c b/src/openvpn/push.c index a1b999e..5220bf0 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -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; -- 1.9.1 ------------------------------------------------------------------------------ _______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel