[Openvpn-devel] [PATCH v2] Use separate list for per-client push options
v2: - Also move ifconfig and ipv6-ifconfig to separate options list Move client-specific push options (currently peer-id and cipher) to separate list, which is deallocated after push_reply has been send. This makes sure that options fit into buf, not duplicated nor leak memory on renegotiation. Signed-off-by: Lev Stipakov--- src/openvpn/push.c | 186 ++--- 1 file changed, 104 insertions(+), 82 deletions(-) diff --git a/src/openvpn/push.c b/src/openvpn/push.c index a1b999e..f7bcad1 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -40,26 +40,29 @@ #if P2MP +static char push_reply_cmd[] = "PUSH_REPLY"; + /** - * Add an option to the push list by providing a format string. + * Add an option to the given 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 oThe current connection's options - * @param msglevel The message level to use when printing errors + * @param gc GC arena where options are allocated + * @param push_list Push list containing 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, +static bool push_option_fmt(struct gc_arena *gc, struct push_list *push_list, int msglevel, const char *fmt, ...) #ifdef __GNUC__ #if __USE_MINGW_ANSI_STDIO -__attribute__ ((format (gnu_printf, 3, 4))) +__attribute__ ((format (gnu_printf, 4, 5))) #else -__attribute__ ((format (__printf__, 3, 4))) +__attribute__ ((format (__printf__, 4, 5))) #endif #endif ; @@ -295,16 +298,39 @@ send_push_request (struct context *c) /** * Prepare push options, based on local options and available peer info. * - * @param options Connection options - * @param tls_multiTLS state structure for the current tunnel + * @param context context structure storing data for VPN tunnel + * @param gc gc arena for allocating push options + * @param push_listpush list 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) +prepare_push_reply (struct context *c, struct gc_arena *gc, struct push_list *push_list) { const char *optstr = NULL; + const struct tls_multi *tls_multi = c->c2.tls_multi; const char * const peer_info = tls_multi->peer_info; + struct options *o = >options; + + /* ipv6 */ + if (c->c2.push_ifconfig_ipv6_defined && !o->push_ifconfig_ipv6_blocked) +{ + push_option_fmt (gc, push_list, M_USAGE, "ifconfig-ipv6 %s/%d %s", + print_in6_addr (c->c2.push_ifconfig_ipv6_local, 0, gc), + c->c2.push_ifconfig_ipv6_netbits, + print_in6_addr (c->c2.push_ifconfig_ipv6_remote, 0, gc)); +} + + /* ipv4 */ + if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask) +{ + in_addr_t ifconfig_local = c->c2.push_ifconfig_local; + if (c->c2.push_ifconfig_local_alias) + ifconfig_local = c->c2.push_ifconfig_local_alias; + push_option_fmt (gc, push_list, M_USAGE, "ifconfig %s %s", + print_in_addr_t (ifconfig_local, 0, gc), + print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, gc)); +} /* Send peer-id if client supports it */ optstr = peer_info ? strstr(peer_info, "IV_PROTO=") : NULL; @@ -314,7 +340,7 @@ prepare_push_reply (struct options *o, struct tls_multi *tls_multi) int r = sscanf(optstr, "IV_PROTO=%d", ); if ((r == 1) && (proto >= 2)) { - push_option_fmt(o, M_USAGE, "peer-id %d", tls_multi->peer_id); + push_option_fmt(gc, push_list, M_USAGE, "peer-id %d", tls_multi->peer_id); } } @@ -324,7 +350,7 @@ prepare_push_reply (struct options *o, struct tls_multi *tls_multi) /* if we have already created our key, we cannot change our own * cipher, so disable NCP and warn = explain why */ - struct tls_session *session = _multi->session[TM_ACTIVE]; + const struct tls_session *session = _multi->session[TM_ACTIVE]; if ( session->key[KS_PRIMARY].crypto_options.key_ctx_bi.initialized ) { msg( M_INFO, "PUSH: client wants to negotiate cipher (NCP), but " @@ -335,86 +361,76 @@ 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, >gc); + char *push_cipher =
Re: [Openvpn-devel] strtok on Windows
On Sun, Oct 9, 2016 at 11:02 AM, Selva Nairwrote: > As per MSDN, strtok on Windows is thread-safe --- uses thread-local > static for the internal state (though not reentrant). Anyone knows > whether this is true even when mingw is used --- does it use strtok from > Microsoft's run time or some internal implementation? > Well, I went ahead and tested it: indeed strtok is thread-safe on windows (obviously not reentrant). I guess it uses strtok in MS runtime, not a typical C library implementation. (Tested on Debian jessie with mingw-w64 version 4.9.1-19+14.3.) Selva -- Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot___ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel
[Openvpn-devel] strtok on Windows
Hi, As per MSDN, strtok on Windows is thread-safe --- uses thread-local static for the internal state (though not reentrant). Anyone knows whether this is true even when mingw is used --- does it use strtok from Microsoft's run time or some internal implementation? I have patch for the GUI that uses strtok_r which is not natively available on Windows. Just realized some older versions of mingw doesn't have an implementation of strtok_r. For my use-case a thread-safe strtok will work as reentrancy is not required. Thanks, Selva -- Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot___ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Re: [Openvpn-devel] [PATCH applied] Fix --multihome for IPv6 on 64bit BSD systems.
Thanks, Arne. Patch has been applied to the following branches commit 3fb246e38fc670c7dfff8ce4521c75c95c766c9e (master) commit f7aba873ca593eb2ab8a4a358cd6c06ef46a09e1 (release/2.3) Author: Gert Doering Date: Sun Oct 9 12:09:29 2016 +0200 Fix --multihome for IPv6 on 64bit BSD systems. Signed-off-by: Gert DoeringAcked-by: Arne Schwabe Message-Id: <20161009100929.46472-1-g...@greenie.muc.de> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg12626.html Signed-off-by: Gert Doering -- kind regards, Gert Doering -- Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot ___ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel
[Openvpn-devel] [PATCH] Fix --multihome for IPv6 on 64bit BSD systems.
The old code only worked if "struct openvpn*pktinfo" happened to use the same structure packing as the CMSG_SPACE() / CMSG_LEN() macros (which are part of the official API, see RFC 2292). Get rid of "struct openvpn_*_pktinfo" definitions, replace them by an opaque buffer sized large enough to fit IPv4 and IPv6 packet info messages, as defined by CMSG_SPACE(sizeof(struct ...)). On 32 bit platforms, the net result is the same. On 64 bit platforms, the new buffer is bigger than openvpn_pktinfo was, fixing an overflow with ipi6_ifindex corruption on reception, and EINVAL on sendmsg(). The IPv4 related changes are only side effects of using the new buffer. Fixes: FreeBSD 10.3/amd64, FreeBSD 9.3/sparc64, OpenBSD 6.0/amd64, NetBSD 7.0.1/i386. Note: --multihome for IPv4 on NetBSD is still broken and non-fixable(!) as NetBSD lacks the necessary kernel code for the sendmsg() side. Verified that "--multihome works as well as before" on FreeBSD 7.4/amd64, NetBSD 5.1/amd64, OpenBSD 4.9/i386, Linux/x86_64, Linux/i386, OpenSolaris 10 (--multihome needs -D_XPG4_2, see trac #750) See also: ip(4), ip6(4), recv(2) Trac #634, #327, #28 Signed-off-by: Gert Doering--- src/openvpn/socket.c | 57 +++- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index e096132..184c7ad 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -2863,27 +2863,16 @@ link_socket_read_tcp (struct link_socket *sock, #if ENABLE_IP_PKTINFO -#pragma pack(1) /* needed to keep structure size consistent for 32 vs. 64-bit architectures */ -struct openvpn_in4_pktinfo -{ - struct cmsghdr cmsghdr; +/* make the buffer large enough to handle ancilliary socket data for + * both IPv4 and IPv6 destination addresses, plus padding (see RFC 2292) + */ #if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) - struct in_pktinfo pi4; -#elif defined(IP_RECVDSTADDR) - struct in_addr pi4; +#define PKTINFO_BUF_SIZE max_int( CMSG_SPACE(sizeof (struct in6_pktinfo)), \ + CMSG_SPACE(sizeof (struct in_pktinfo)) ) +#else +#define PKTINFO_BUF_SIZE max_int( CMSG_SPACE(sizeof (struct in6_pktinfo)), \ + CMSG_SPACE(sizeof (struct in_addr)) ) #endif -}; -struct openvpn_in6_pktinfo -{ - struct cmsghdr cmsghdr; - struct in6_pktinfo pi6; -}; - -union openvpn_pktinfo { - struct openvpn_in4_pktinfo msgpi4; - struct openvpn_in6_pktinfo msgpi6; -}; -#pragma pack() static socklen_t link_socket_read_udp_posix_recvmsg (struct link_socket *sock, @@ -2891,7 +2880,7 @@ link_socket_read_udp_posix_recvmsg (struct link_socket *sock, struct link_socket_actual *from) { struct iovec iov; - union openvpn_pktinfo opi; + uint8_t pktinfo_buf[PKTINFO_BUF_SIZE]; struct msghdr mesg; socklen_t fromlen = sizeof (from->dest.addr); @@ -2901,8 +2890,8 @@ link_socket_read_udp_posix_recvmsg (struct link_socket *sock, mesg.msg_iovlen = 1; mesg.msg_name = >dest.addr; mesg.msg_namelen = fromlen; - mesg.msg_control = - mesg.msg_controllen = sizeof opi; + mesg.msg_control = pktinfo_buf; + mesg.msg_controllen = sizeof pktinfo_buf; buf->len = recvmsg (sock->sd, , 0); if (buf->len >= 0) { @@ -2914,13 +2903,14 @@ link_socket_read_udp_posix_recvmsg (struct link_socket *sock, #if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) && cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO + && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct in_pktinfo)) ) #elif defined(IP_RECVDSTADDR) && cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR + && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct in_addr)) ) #else #error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h) #endif - && cmsg->cmsg_len >= sizeof (struct openvpn_in4_pktinfo)) { #if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) struct in_pktinfo *pkti = (struct in_pktinfo *) CMSG_DATA (cmsg); @@ -2936,7 +2926,7 @@ link_socket_read_udp_posix_recvmsg (struct link_socket *sock, && CMSG_NXTHDR (, cmsg) == NULL && cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO - && cmsg->cmsg_len >= sizeof (struct openvpn_in6_pktinfo)) + && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct in6_pktinfo)) ) { struct in6_pktinfo *pkti6 = (struct in6_pktinfo *) CMSG_DATA (cmsg); from->pi.in6.ipi6_ifindex = pkti6->ipi6_ifindex; @@ -3007,7 +2997,7 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock, struct iovec iov; struct msghdr mesg; struct cmsghdr *cmsg; - union openvpn_pktinfo opi; + uint8_t pktinfo_buf[PKTINFO_BUF_SIZE]; iov.iov_base = BPTR (buf); iov.iov_len = BLEN (buf); @@ -3019,12 +3009,12 @@