diff options
28 files changed, 936 insertions, 247 deletions
| diff --git a/build.gradle b/build.gradle index d24e4df0..9e6e9415 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ buildscript {          classpath 'com.android.tools.build:gradle:0.4'      }  } +  apply plugin: 'android'  dependencies { diff --git a/openvpn/Makefile.am b/openvpn/Makefile.am index c5805797..1a30aa5a 100644 --- a/openvpn/Makefile.am +++ b/openvpn/Makefile.am @@ -66,7 +66,6 @@ dist_doc_DATA = \  dist_noinst_DATA = \  	.gitignore \  	.gitattributes \ -	config-version.h.in \  	PORTS \  	README.IPv6 TODO.IPv6 \  	README.polarssl \ @@ -91,8 +90,12 @@ root_DATA = version.sh  endif  config-version.h: -	@CONFIGURE_GIT_REVISION="`GIT_DIR=\"$(top_srcdir)/.git\" $(GIT) rev-parse --symbolic-full-name HEAD`/`GIT_DIR=\"$(top_srcdir)/.git\" $(GIT) rev-parse --short=16 HEAD`"; \ -		$(SED) "s#@CONFIGURE_GIT_REVISION[@]#$${CONFIGURE_GIT_REVISION}#g" "$(srcdir)/config-version.h.in" > config-version.h.tmp +	@CONFIGURE_GIT_CHFILES="`GIT_DIR=\"$(top_srcdir)/.git\" $(GIT) diff-files --name-status -r --ignore-submodules --quiet -- || echo \"+\"`"; \ +	CONFIGURE_GIT_UNCOMMITTED="`GIT_DIR=\"$(top_srcdir)/.git\" $(GIT) diff-index --cached  --quiet --ignore-submodules HEAD || echo \"*\"`"; \ +	CONFIGURE_GIT_REVISION="`GIT_DIR=\"$(top_srcdir)/.git\" $(GIT) rev-parse --symbolic-full-name HEAD | cut -d/ -f3-`/`GIT_DIR=\"$(top_srcdir)/.git\" $(GIT) rev-parse --short=16 HEAD`"; \ +	echo "#define CONFIGURE_GIT_REVISION \"$${CONFIGURE_GIT_REVISION}\"" > config-version.h.tmp; \ +	echo "#define CONFIGURE_GIT_FLAGS \"$${CONFIGURE_GIT_CHFILES}$${CONFIGURE_GIT_UNCOMMITTED}\"" >> config-version.h.tmp +  	@if ! [ -f config-version.h ] || ! cmp -s config-version.h.tmp config-version.h; then \  		echo "replacing config-version.h"; \  		mv config-version.h.tmp config-version.h; \ diff --git a/openvpn/config-version.h.in b/openvpn/config-version.h.in deleted file mode 100644 index 27ee36af..00000000 --- a/openvpn/config-version.h.in +++ /dev/null @@ -1 +0,0 @@ -#define CONFIGURE_GIT_REVISION "@CONFIGURE_GIT_REVISION@" diff --git a/openvpn/doc/doxygen/openvpn.doxyfile b/openvpn/doc/doxygen/openvpn.doxyfile index 5d87172c..cf26c42a 100644 --- a/openvpn/doc/doxygen/openvpn.doxyfile +++ b/openvpn/doc/doxygen/openvpn.doxyfile @@ -235,7 +235,7 @@ EXPAND_ONLY_PREDEF     = NO  SEARCH_INCLUDES        = YES  INCLUDE_PATH           =  INCLUDE_FILE_PATTERNS  = -PREDEFINED             = WIN32 NTLM USE_LZO ENABLE_FRAGMENT P2MP P2MP_SERVER USE_CRYPTO USE_SSL ENABLE_PLUGIN ENABLE_MANAGEMENT ENABLE_OCC HAVE_GETTIMEOFDAY +PREDEFINED             = WIN32 NTLM USE_LZO ENABLE_FRAGMENT P2MP P2MP_SERVER ENABLE_CRYPTO ENABLE_CRYPTO_OPENSSL ENABLE_SSL ENABLE_PLUGIN ENABLE_MANAGEMENT ENABLE_OCC HAVE_GETTIMEOFDAY  EXPAND_AS_DEFINED      =  SKIP_FUNCTION_MACROS   = YES  #--------------------------------------------------------------------------- diff --git a/openvpn/doc/openvpn.8 b/openvpn/doc/openvpn.8 index 4ae351a0..15dd3206 100644 --- a/openvpn/doc/openvpn.8 +++ b/openvpn/doc/openvpn.8 @@ -2506,6 +2506,7 @@ Allow management interface to override  .B \-\-remote  directives (client-only).  .\"********************************************************* +.TP  .B \-\-management-external-key  Allows usage for external private key file instead of  .B \-\-key diff --git a/openvpn/src/openvpn/comp.c b/openvpn/src/openvpn/comp.c new file mode 100644 index 00000000..96922571 --- /dev/null +++ b/openvpn/src/openvpn/comp.c @@ -0,0 +1,135 @@ +/* + *  OpenVPN -- An application to securely tunnel IP networks + *             over a single UDP port, with support for SSL/TLS-based + *             session authentication and key exchange, + *             packet encryption, packet authentication, and + *             packet compression. + * + *  Copyright (C) 2002-2012 OpenVPN Technologies, Inc. <sales@openvpn.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License version 2 + *  as published by the Free Software Foundation. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program (see the file COPYING included with this + *  distribution); if not, write to the Free Software Foundation, Inc., + *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#include "syshead.h" + +#ifdef USE_COMP + +#include "comp.h" +#include "error.h" +#include "otime.h" + +#include "memdbg.h" + +struct compress_context * +comp_init(const struct compress_options *opt) +{ +  struct compress_context *compctx = NULL; +  switch (opt->alg) +    { +    case COMP_ALG_STUB: +      ALLOC_OBJ_CLEAR (compctx, struct compress_context); +      compctx->flags = opt->flags; +      compctx->alg = comp_stub_alg; +      (*compctx->alg.compress_init)(compctx); +      break; +#ifdef ENABLE_LZO +    case COMP_ALG_LZO: +      ALLOC_OBJ_CLEAR (compctx, struct compress_context); +      compctx->flags = opt->flags; +      compctx->alg = lzo_alg; +      (*compctx->alg.compress_init)(compctx); +      break; +#endif +#ifdef ENABLE_SNAPPY +    case COMP_ALG_SNAPPY: +      ALLOC_OBJ_CLEAR (compctx, struct compress_context); +      compctx->flags = opt->flags; +      compctx->alg = snappy_alg; +      (*compctx->alg.compress_init)(compctx); +      break; +#endif +    } +  return compctx; +} + +void +comp_uninit(struct compress_context *compctx) +{ +  if (compctx) +    { +      (*compctx->alg.compress_uninit)(compctx); +      free(compctx); +    } +} + +void +comp_add_to_extra_frame(struct frame *frame) +{ +  /* Leave room for our one-byte compressed/didn't-compress prefix byte. */ +  frame_add_to_extra_frame (frame, COMP_PREFIX_LEN); +} + +void +comp_add_to_extra_buffer(struct frame *frame) +{ +  /* Leave room for compression buffer to expand in worst case scenario +     where data is totally uncompressible */ +  frame_add_to_extra_buffer (frame, COMP_EXTRA_BUFFER (EXPANDED_SIZE(frame))); +} + +void +comp_print_stats (const struct compress_context *compctx, struct status_output *so) +{ +  if (compctx) +    { +      status_printf (so, "pre-compress bytes," counter_format, compctx->pre_compress); +      status_printf (so, "post-compress bytes," counter_format, compctx->post_compress); +      status_printf (so, "pre-decompress bytes," counter_format, compctx->pre_decompress); +      status_printf (so, "post-decompress bytes," counter_format, compctx->post_decompress); +    } +} + +/* + * Tell our peer which compression algorithms we support. + */ +void +comp_generate_peer_info_string(const struct compress_options *opt, struct buffer *out) +{ +  if (opt) +    { +      bool lzo_avail = false; +      if (!(opt->flags & COMP_F_ADVERTISE_STUBS_ONLY)) +	{ +#if defined(ENABLE_SNAPPY) +	  buf_printf (out, "IV_SNAPPY=1\n"); +#endif +#if defined(ENABLE_LZO) +	  buf_printf (out, "IV_LZO=1\n"); +	  lzo_avail = true; +#endif +	} +      if (!lzo_avail) +	buf_printf (out, "IV_LZO_STUB=1\n"); +      buf_printf (out, "IV_COMP_STUB=1\n"); +    } +} + +#endif /* USE_COMP */ diff --git a/openvpn/src/openvpn/comp.h b/openvpn/src/openvpn/comp.h new file mode 100644 index 00000000..0d2f1bc9 --- /dev/null +++ b/openvpn/src/openvpn/comp.h @@ -0,0 +1,171 @@ +/* + *  OpenVPN -- An application to securely tunnel IP networks + *             over a single UDP port, with support for SSL/TLS-based + *             session authentication and key exchange, + *             packet encryption, packet authentication, and + *             packet compression. + * + *  Copyright (C) 2002-2012 OpenVPN Technologies, Inc. <sales@openvpn.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License version 2 + *  as published by the Free Software Foundation. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program (see the file COPYING included with this + *  distribution); if not, write to the Free Software Foundation, Inc., + *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +/* + * Generic compression support.  Currently we support + * Snappy and LZO 2. + */ +#ifndef OPENVPN_COMP_H +#define OPENVPN_COMP_H + +#ifdef USE_COMP + +#include "buffer.h" +#include "mtu.h" +#include "common.h" +#include "status.h" + +/* algorithms */ +#define COMP_ALG_UNDEF  0 +#define COMP_ALG_STUB   1 /* support compression command byte and framing without actual compression */ +#define COMP_ALG_LZO    2 /* LZO algorithm */ +#define COMP_ALG_SNAPPY 3 /* Snappy algorithm */ + +/* Compression flags */ +#define COMP_F_ADAPTIVE   (1<<0) /* COMP_ALG_LZO only */ +#define COMP_F_ASYM       (1<<1) /* only downlink is compressed, not uplink */ +#define COMP_F_SWAP       (1<<2) /* initial command byte is swapped with last byte in buffer to preserve payload alignment */ +#define COMP_F_ADVERTISE_STUBS_ONLY (1<<3) /* tell server that we only support compression stubs */ + +/* + * Length of prepended prefix on compressed packets + */ +#define COMP_PREFIX_LEN 1 + +/* + * Prefix bytes + */ +#define NO_COMPRESS_BYTE      0xFA +#define NO_COMPRESS_BYTE_SWAP 0xFB /* to maintain payload alignment, replace this byte with last byte of packet */ + +/* + * Compress worst case size expansion (for any algorithm) + * + * LZO:    len + len/8 + 128 + 3 + * Snappy: len + len/6 + 32 + */ +#define COMP_EXTRA_BUFFER(len) ((len)/6 + 128 + 3 + COMP_PREFIX_LEN) + +/* + * Don't try to compress any packet smaller than this. + */ +#define COMPRESS_THRESHOLD 100 + +/* Forward declaration of compression context */ +struct compress_context; + +/* + * Virtual methods and other static info for each compression algorithm + */ +struct compress_alg +{ +  const char *name; +  void (*compress_init)(struct compress_context *compctx); +  void (*compress_uninit)(struct compress_context *compctx); +  void (*compress)(struct buffer *buf, struct buffer work, +		   struct compress_context *compctx, +		   const struct frame* frame); + +  void (*decompress)(struct buffer *buf, struct buffer work, +		     struct compress_context *compctx, +		     const struct frame* frame); +}; + +/* + * Headers for each compression implementation + */ +#ifdef ENABLE_LZO +#include "lzo.h" +#endif + +#ifdef ENABLE_SNAPPY +#include "snappy.h" +#endif + +/* + * Information that basically identifies a compression + * algorithm and related flags. + */ +struct compress_options +{ +  int alg; +  unsigned int flags; +}; + +/* + * Workspace union of all supported compression algorithms + */ +union compress_workspace_union +{ +#ifdef ENABLE_LZO +  struct lzo_compress_workspace lzo; +#endif +#ifdef ENABLE_SNAPPY +  struct snappy_workspace snappy; +#endif +}; + +/* + * Context for active compression session + */ +struct compress_context +{ +  unsigned int flags; +  struct compress_alg alg; +  union compress_workspace_union wu; + +  /* statistics */ +  counter_type pre_decompress; +  counter_type post_decompress; +  counter_type pre_compress; +  counter_type post_compress; +}; + +extern const struct compress_alg comp_stub_alg; + +struct compress_context *comp_init(const struct compress_options *opt); + +void comp_uninit(struct compress_context *compctx); + +void comp_add_to_extra_frame(struct frame *frame); +void comp_add_to_extra_buffer(struct frame *frame); + +void comp_print_stats (const struct compress_context *compctx, struct status_output *so); + +void comp_generate_peer_info_string(const struct compress_options *opt, struct buffer *out); + +static inline bool +comp_enabled(const struct compress_options *info) +{ +  return info->alg != COMP_ALG_UNDEF; +} + +static inline bool +comp_unswapped_prefix(const struct compress_options *info) +{ +  return !(info->flags & COMP_F_SWAP); +} + +#endif /* USE_COMP */ +#endif diff --git a/openvpn/src/openvpn/compstub.c b/openvpn/src/openvpn/compstub.c new file mode 100644 index 00000000..2ab7163e --- /dev/null +++ b/openvpn/src/openvpn/compstub.c @@ -0,0 +1,118 @@ +/* + *  OpenVPN -- An application to securely tunnel IP networks + *             over a single UDP port, with support for SSL/TLS-based + *             session authentication and key exchange, + *             packet encryption, packet authentication, and + *             packet compression. + * + *  Copyright (C) 2002-2012 OpenVPN Technologies, Inc. <sales@openvpn.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License version 2 + *  as published by the Free Software Foundation. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program (see the file COPYING included with this + *  distribution); if not, write to the Free Software Foundation, Inc., + *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#include "syshead.h" + +#if defined(USE_COMP) + +#include "comp.h" +#include "error.h" +#include "otime.h" + +#include "memdbg.h" + +static void +stub_compress_init (struct compress_context *compctx) +{ +} + +static void +stub_compress_uninit (struct compress_context *compctx) +{ +} + +static void +stub_compress (struct buffer *buf, struct buffer work, +	       struct compress_context *compctx, +	       const struct frame* frame) +{ +  if (buf->len <= 0) +    return; +  if (compctx->flags & COMP_F_SWAP) +    { +      uint8_t *head = BPTR (buf); +      uint8_t *tail  = BEND (buf); +      ASSERT (buf_safe (buf, 1)); +      ++buf->len; + +      /* move head byte of payload to tail */ +      *tail = *head; +      *head = NO_COMPRESS_BYTE_SWAP; +    } +  else +    { +      uint8_t *header = buf_prepend (buf, 1); +      *header = NO_COMPRESS_BYTE; +    } +} + +static void +stub_decompress (struct buffer *buf, struct buffer work, +		 struct compress_context *compctx, +		 const struct frame* frame) +{ +  uint8_t c; +  if (buf->len <= 0) +    return; +  if (compctx->flags & COMP_F_SWAP) +    { +      uint8_t *head = BPTR (buf); +      c = *head; +      --buf->len; +      *head = *BEND (buf); +      if (c != NO_COMPRESS_BYTE_SWAP) +	{ +	  dmsg (D_COMP_ERRORS, "Bad compression stub (swap) decompression header byte: %d", c); +	  buf->len = 0; +	} +    } +  else +    { +      c = *BPTR (buf); +      ASSERT (buf_advance (buf, 1)); +      if (c != NO_COMPRESS_BYTE) +	{ +	  dmsg (D_COMP_ERRORS, "Bad compression stub decompression header byte: %d", c); +	  buf->len = 0; +	} +    } +} + +const struct compress_alg comp_stub_alg = { +  "stub", +  stub_compress_init, +  stub_compress_uninit, +  stub_compress, +  stub_decompress +}; + +#else +static void dummy(void) {} +#endif /* USE_STUB */ diff --git a/openvpn/src/openvpn/crypto_openssl.c b/openvpn/src/openvpn/crypto_openssl.c index 21d1762d..1501bc86 100644 --- a/openvpn/src/openvpn/crypto_openssl.c +++ b/openvpn/src/openvpn/crypto_openssl.c @@ -194,7 +194,8 @@ crypto_init_lib_engine (const char *engine_name)  void  crypto_init_lib (void)  { -#ifndef USE_SSL +#ifndef ENABLE_SSL +  /* If SSL is enabled init is taken care of in ssl_openssl.c */  #ifndef ENABLE_SMALL    ERR_load_crypto_strings ();  #endif @@ -215,7 +216,8 @@ crypto_init_lib (void)  void  crypto_uninit_lib (void)  { -#ifndef USE_SSL +#ifndef ENABLE_SSL +  /* If SSL is enabled cleanup is taken care of in ssl_openssl.c */    EVP_cleanup ();  #ifndef ENABLE_SMALL    ERR_free_strings (); diff --git a/openvpn/src/openvpn/error.c b/openvpn/src/openvpn/error.c index d9450a6c..98611a1b 100644 --- a/openvpn/src/openvpn/error.c +++ b/openvpn/src/openvpn/error.c @@ -404,7 +404,6 @@ void  assert_failed (const char *filename, int line)  {  #ifdef GOOGLE_BREAKPAD -    msg (M_NONFATAL, "Assertion failed at %s:%d", filename, line);      breakpad_dodump();  #endif    msg (M_FATAL, "Assertion failed at %s:%d", filename, line); diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c index 4af79657..335ebab1 100644 --- a/openvpn/src/openvpn/init.c +++ b/openvpn/src/openvpn/init.c @@ -1156,13 +1156,14 @@ do_init_traffic_shaper (struct context *c)  }  /* - * Allocate a route list structure if at least one - * --route option was specified. + * Allocate route list structures for IPv4 and IPv6 + * (we do this for IPv4 even if no --route option has been seen, as other + * parts of OpenVPN might want to fill the route-list with info, e.g. DHCP)   */  static void  do_alloc_route_list (struct context *c)  { -  if (c->options.routes && !c->c1.route_list) +  if (!c->c1.route_list)      c->c1.route_list = new_route_list (c->options.max_routes, &c->gc);    if (c->options.routes_ipv6 && !c->c1.route_ipv6_list)      c->c1.route_ipv6_list = new_route_ipv6_list (c->options.max_routes, &c->gc); @@ -1420,15 +1421,15 @@ do_open_tun (struct context *c)    if (!c->c1.tuntap)      {  #endif -       +  #ifdef TARGET_ANDROID        /* If we emulate persist-tun on android we still have to open a new tun and           then close the old */        int oldtunfd=-1; -      if(c->c1.tuntap) +      if (c->c1.tuntap)            oldtunfd = c->c1.tuntap->fd;  #endif -         +        /* initialize (but do not open) tun/tap object */        do_init_tun (c); @@ -1455,17 +1456,17 @@ do_open_tun (struct context *c)  	}        /* possibly add routes */ -      if(ifconfig_order() == ROUTE_BEFORE_TUN) { -		  /* Ignore route_delay, would cause ROUTE_BEFORE_TUN to be ignored */ -		  do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list, -					c->c1.tuntap, c->plugins, c->c2.es); -    } +      if (route_order() == ROUTE_BEFORE_TUN) { +        /* Ignore route_delay, would cause ROUTE_BEFORE_TUN to be ignored */ +        do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list, +                  c->c1.tuntap, c->plugins, c->c2.es); +      }        /* open the tun device */        open_tun (c->options.dev, c->options.dev_type, c->options.dev_node,  		c->c1.tuntap);  #ifdef TARGET_ANDROID -      if(oldtunfd>=0) +      if (oldtunfd>=0)          close(oldtunfd);  #endif        /* set the hardware address */ @@ -1495,7 +1496,7 @@ do_open_tun (struct context *c)  		   c->c2.es);        /* possibly add routes */ -      if ((ifconfig_order() == ROUTE_AFTER_TUN) && (!c->options.route_delay_defined)) +      if ((route_order() == ROUTE_AFTER_TUN) && (!c->options.route_delay_defined))  	do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,  		  c->c1.tuntap, c->plugins, c->c2.es); @@ -1705,7 +1706,7 @@ do_up (struct context *c, bool pulled_options, unsigned int option_types_found)  #endif  	  /* if --route-delay was specified, start timer */ -	  if ((ifconfig_order() == ROUTE_AFTER_TUN) && c->options.route_delay_defined) +	  if ((route_order() == ROUTE_AFTER_TUN) && c->options.route_delay_defined)  	    {  	      event_timeout_init (&c->c2.route_wakeup, c->options.route_delay, now);  	      event_timeout_init (&c->c2.route_wakeup_expire, c->options.route_delay + c->options.route_delay_window, now); @@ -2544,6 +2545,12 @@ do_option_warnings (struct context *c)      msg (M_WARN, "NOTE: --connect-timeout option is not supported on this OS");  #endif +  if (script_security >= SSEC_SCRIPTS) +    msg (M_WARN, "NOTE: the current --script-security setting may allow this configuration to call user-defined scripts"); +  else if (script_security >= SSEC_PW_ENV) +    msg (M_WARN, "WARNING: the current --script-security setting may allow passwords to be passed to scripts via environmental variables"); +  else +    msg (M_WARN, "NOTE: " PACKAGE_NAME " 2.1 requires '--script-security 2' or higher to call user-defined scripts or executables");  }  static void @@ -3681,10 +3688,6 @@ inherit_context_child (struct context *dest,        dest->c2.link_socket_info->lsa = &dest->c1.link_socket_addr;        dest->c2.link_socket_info->connection_established = false;      } - -#ifdef USE_COMP -  dest->c2.comp_context = NULL; -#endif  }  void diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c index c4e834b2..4e96d07f 100644 --- a/openvpn/src/openvpn/manage.c +++ b/openvpn/src/openvpn/manage.c @@ -1781,77 +1781,90 @@ man_io_error (struct management *man, const char *prefix)  }  #ifdef TARGET_ANDROID -static ssize_t write_fd (int fd, void *ptr, size_t nbytes, int flags, int sendfd) -{ -    struct msghdr msg; -    struct iovec iov[1]; -     -    union { -        struct cmsghdr cm; -        char    control[CMSG_SPACE(sizeof(int))]; -    } control_un; -    struct cmsghdr *cmptr; -     -    msg.msg_control = control_un.control; -    msg.msg_controllen = sizeof(control_un.control); -     -    cmptr = CMSG_FIRSTHDR(&msg); -    cmptr->cmsg_len = CMSG_LEN(sizeof(int)); -    cmptr->cmsg_level = SOL_SOCKET; -    cmptr->cmsg_type = SCM_RIGHTS; -    *((int *) CMSG_DATA(cmptr)) = sendfd; -     -    msg.msg_name = NULL; -    msg.msg_namelen = 0; -     -    iov[0].iov_base = ptr; -    iov[0].iov_len = nbytes; -    msg.msg_iov = iov; -    msg.msg_iovlen = 1; -     -    return (sendmsg(fd, &msg, flags)); -} - -static ssize_t read_fd(int fd, void *ptr, size_t nbytes, int flags, int *recvfd) -{ -    struct msghdr msghdr; -    struct iovec iov[1]; -    ssize_t n; -     -    union { -        struct cmsghdr cm; -        char     control[CMSG_SPACE(sizeof (int))]; -    } control_un; -    struct cmsghdr  *cmptr; -     -    msghdr.msg_control  = control_un.control; -    msghdr.msg_controllen = sizeof(control_un.control); -     -    msghdr.msg_name = NULL; -    msghdr.msg_namelen = 0; -     -    iov[0].iov_base = ptr; -    iov[0].iov_len = nbytes; -    msghdr.msg_iov = iov; -    msghdr.msg_iovlen = 1; -     -    if ( (n = recvmsg(fd, &msghdr, flags)) <= 0) -        return (n); -     -    if ( (cmptr = CMSG_FIRSTHDR(&msghdr)) != NULL && -        cmptr->cmsg_len == CMSG_LEN(sizeof(int))) { -        if (cmptr->cmsg_level != SOL_SOCKET) -            msg (M_ERR, "control level != SOL_SOCKET"); -        if (cmptr->cmsg_type != SCM_RIGHTS) -            msg (M_ERR, "control type != SCM_RIGHTS"); -        *recvfd = *((int *) CMSG_DATA(cmptr)); -    } else -        *recvfd = -1;           /* descriptor was not passed */ -     +static ssize_t man_send_with_fd (int fd, void *ptr, size_t nbytes, int flags, int sendfd) +{ +  struct msghdr msg; +  struct iovec iov[1]; + +  union { +    struct cmsghdr cm; +    char    control[CMSG_SPACE(sizeof(int))]; +  } control_un; +  struct cmsghdr *cmptr; + +  msg.msg_control = control_un.control; +  msg.msg_controllen = sizeof(control_un.control); + +  cmptr = CMSG_FIRSTHDR(&msg); +  cmptr->cmsg_len = CMSG_LEN(sizeof(int)); +  cmptr->cmsg_level = SOL_SOCKET; +  cmptr->cmsg_type = SCM_RIGHTS; +  *((int *) CMSG_DATA(cmptr)) = sendfd; + +  msg.msg_name = NULL; +  msg.msg_namelen = 0; + +  iov[0].iov_base = ptr; +  iov[0].iov_len = nbytes; +  msg.msg_iov = iov; +  msg.msg_iovlen = 1; + +  return (sendmsg(fd, &msg, flags)); +} + +static ssize_t man_recv_with_fd (int fd, void *ptr, size_t nbytes, int flags, int *recvfd) +{ +  struct msghdr msghdr; +  struct iovec iov[1]; +  ssize_t n; + +  union { +    struct cmsghdr cm; +    char     control[CMSG_SPACE(sizeof (int))]; +  } control_un; +  struct cmsghdr  *cmptr; + +  msghdr.msg_control  = control_un.control; +  msghdr.msg_controllen = sizeof(control_un.control); + +  msghdr.msg_name = NULL; +  msghdr.msg_namelen = 0; + +  iov[0].iov_base = ptr; +  iov[0].iov_len = nbytes; +  msghdr.msg_iov = iov; +  msghdr.msg_iovlen = 1; + +  if ( (n = recvmsg(fd, &msghdr, flags)) <= 0)      return (n); + +  if ( (cmptr = CMSG_FIRSTHDR(&msghdr)) != NULL && +       cmptr->cmsg_len == CMSG_LEN(sizeof(int))) { +    if (cmptr->cmsg_level != SOL_SOCKET) +      msg (M_ERR, "control level != SOL_SOCKET"); +    if (cmptr->cmsg_type != SCM_RIGHTS) +      msg (M_ERR, "control type != SCM_RIGHTS"); +    *recvfd = *((int *) CMSG_DATA(cmptr)); +  } else +    *recvfd = -1;           /* descriptor was not passed */ + +  return (n);  } -#endif +/* + * The android control method will instruct the GUI part of openvpn to do + * the route/ifconfig/open tun command.   See doc/android.txt for details. + */ +bool management_android_control (struct management *man, const char *command, const char *msg) +{ +  struct user_pass up; +  CLEAR(up); +  strncpy (up.username, msg, sizeof(up.username)-1); + +  management_query_user_pass(management, &up , command, GET_USER_PASS_NEED_OK,(void*) 0); +  return strcmp ("ok", up.password)==0; +} +#endif  static int  man_read (struct management *man) @@ -1864,8 +1877,8 @@ man_read (struct management *man)  #ifdef TARGET_ANDROID    int fd; -  len = read_fd (man->connection.sd_cli, buf, sizeof (buf), MSG_NOSIGNAL, &fd); -  if(fd >= 0)  +  len = man_recv_with_fd (man->connection.sd_cli, buf, sizeof (buf), MSG_NOSIGNAL, &fd); +  if(fd >= 0)       man->connection.lastfdreceived = fd;  #else    len = recv (man->connection.sd_cli, buf, sizeof (buf), MSG_NOSIGNAL); @@ -1948,9 +1961,9 @@ man_write (struct management *man)      {        const int len = min_int (size_hint, BLEN (buf));  #ifdef TARGET_ANDROID -      if (man->connection.fdtosend > 0)  +      if (man->connection.fdtosend > 0)          { -         sent = write_fd (man->connection.sd_cli, BPTR (buf), len, MSG_NOSIGNAL,man->connection.fdtosend); +         sent = man_send_with_fd (man->connection.sd_cli, BPTR (buf), len, MSG_NOSIGNAL,man->connection.fdtosend);              man->connection.fdtosend = -1;          } else  #endif diff --git a/openvpn/src/openvpn/manage.h b/openvpn/src/openvpn/manage.h index d2790dd4..962b5bc4 100644 --- a/openvpn/src/openvpn/manage.h +++ b/openvpn/src/openvpn/manage.h @@ -300,8 +300,8 @@ struct man_connection {    struct buffer_list *rsa_sig;  #endif  #ifdef TARGET_ANDROID -    int fdtosend; -    int lastfdreceived; +  int fdtosend; +  int lastfdreceived;  #endif  }; @@ -376,6 +376,10 @@ bool management_query_user_pass (struct management *man,  				 const unsigned int flags,  				 const char *static_challenge); +#ifdef TARGET_ANDROID +bool management_android_control (struct management *man, const char *command, const char *msg); +#endif +  bool management_should_daemonize (struct management *man);  bool management_would_hold (struct management *man);  bool management_hold (struct management *man); diff --git a/openvpn/src/openvpn/multi.c b/openvpn/src/openvpn/multi.c index ab3f10cb..f016b149 100644 --- a/openvpn/src/openvpn/multi.c +++ b/openvpn/src/openvpn/multi.c @@ -807,8 +807,8 @@ multi_print_status (struct multi_context *m, struct status_output *so, const int  	   */  	  status_printf (so, "TITLE%c%s", sep, title_string);  	  status_printf (so, "TIME%c%s%c%u", sep, time_string (now, 0, false, &gc_top), sep, (unsigned int)now); -	  status_printf (so, "HEADER%cCLIENT_LIST%cCommon Name%cReal Address%cVirtual Address%cBytes Received%cBytes Sent%cConnected Since%cConnected Since (time_t)%cUsername", -			 sep, sep, sep, sep, sep, sep, sep, sep, sep); +	  status_printf (so, "HEADER%cCLIENT_LIST%cCommon Name%cReal Address%cVirtual Address%cVirtual IPv6 Address%cBytes Received%cBytes Sent%cConnected Since%cConnected Since (time_t)%cUsername%cClient ID", +			 sep, sep, sep, sep, sep, sep, sep, sep, sep, sep, sep);  	  hash_iterator_init (m->hash, &hi);  	  while ((he = hash_iterator_next (&hi)))  	    { @@ -817,15 +817,26 @@ multi_print_status (struct multi_context *m, struct status_output *so, const int  	      if (!mi->halt)  		{ -		  status_printf (so, "CLIENT_LIST%c%s%c%s%c%s%c" counter_format "%c" counter_format "%c%s%c%u%c%s", +		  status_printf (so, "CLIENT_LIST%c%s%c%s%c%s%c%s%c" counter_format "%c" counter_format "%c%s%c%u%c%s%c" +#ifdef MANAGEMENT_DEF_AUTH +				 "%lu", +#else +				 "", +#endif  				 sep, tls_common_name (mi->context.c2.tls_multi, false),  				 sep, mroute_addr_print (&mi->real, &gc),  				 sep, print_in_addr_t (mi->reporting_addr, IA_EMPTY_IF_UNDEF, &gc), +				 sep, print_in6_addr (mi->reporting_addr_ipv6, IA_EMPTY_IF_UNDEF, &gc),  				 sep, mi->context.c2.link_read_bytes,  				 sep, mi->context.c2.link_write_bytes,  				 sep, time_string (mi->created, 0, false, &gc),  				 sep, (unsigned int)mi->created, -				 sep, tls_username (mi->context.c2.tls_multi, false)); +				 sep, tls_username (mi->context.c2.tls_multi, false), +#ifdef MANAGEMENT_DEF_AUTH +				 sep, mi->context.c2.mda_context.cid); +#else +				 sep); +#endif  		}  	      gc_free (&gc);  	    } @@ -1847,6 +1858,7 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi  	  /* set our client's VPN endpoint for status reporting purposes */  	  mi->reporting_addr = mi->context.c2.push_ifconfig_local; +	  mi->reporting_addr_ipv6 = mi->context.c2.push_ifconfig_ipv6_local;  	  /* set context-level authentication flag */  	  mi->context.c2.context_auth = CAS_SUCCEEDED; diff --git a/openvpn/src/openvpn/multi.h b/openvpn/src/openvpn/multi.h index 2bc0c8a1..fc2ffb24 100644 --- a/openvpn/src/openvpn/multi.h +++ b/openvpn/src/openvpn/multi.h @@ -88,6 +88,7 @@ struct multi_instance {    bool socket_set_called;    in_addr_t reporting_addr;       /* IP address shown in status listing */ +  struct in6_addr reporting_addr_ipv6;  /* IPv6 address in status listing */    bool did_open_context;    bool did_real_hash; diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c index 7dba31a7..37909ca9 100644 --- a/openvpn/src/openvpn/options.c +++ b/openvpn/src/openvpn/options.c @@ -64,6 +64,9 @@  const char title_string[] =    PACKAGE_STRING +#ifdef CONFIGURE_GIT_REVISION +        " [git:" CONFIGURE_GIT_REVISION CONFIGURE_GIT_FLAGS "]" +#endif    " " TARGET_ALIAS  #ifdef ENABLE_CRYPTO  #ifdef ENABLE_SSL @@ -1132,7 +1135,7 @@ show_tuntap_options (const struct tuntap_options *o)  #endif  #endif -#if defined(WIN32) || defined(TARGET_ANDROID)  +#if defined(WIN32) || defined(TARGET_ANDROID)  static void  dhcp_option_address_parse (const char *name, const char *parm, in_addr_t *array, int *len, int msglevel)  { @@ -3410,9 +3413,6 @@ usage_version (void)  #ifdef CONFIGURE_SPECIAL_BUILD    msg (M_INFO|M_NOPREFIX, "special build: %s", CONFIGURE_SPECIAL_BUILD);  #endif -#ifdef CONFIGURE_GIT_REVISION -  msg (M_INFO|M_NOPREFIX, "git revision: %s", CONFIGURE_GIT_REVISION); -#endif  #endif    openvpn_exit (OPENVPN_EXIT_STATUS_USAGE); /* exit point */  } diff --git a/openvpn/src/openvpn/pf.c b/openvpn/src/openvpn/pf.c index aafe9ff0..461beed7 100644 --- a/openvpn/src/openvpn/pf.c +++ b/openvpn/src/openvpn/pf.c @@ -417,7 +417,7 @@ lookup_cn_rule (struct hash *h, const char *cn, const uint32_t cn_hash)  bool  pf_cn_test (struct pf_set *pfs, const struct tls_multi *tm, const int type, const char *prefix)  { -  if (!pfs->kill) +  if (pfs && !pfs->kill)      {        const char *cn;        uint32_t cn_hash; diff --git a/openvpn/src/openvpn/route.c b/openvpn/src/openvpn/route.c index 03574b9e..c5a7ba6b 100644 --- a/openvpn/src/openvpn/route.c +++ b/openvpn/src/openvpn/route.c @@ -503,6 +503,7 @@ route_list_add_vpn_gateway (struct route_list *rl,  			    struct env_set *es,  			    const in_addr_t addr)  { +  ASSERT(rl);    rl->spec.remote_endpoint = addr;    rl->spec.flags |= RTSA_REMOTE_ENDPOINT;    setenv_route_addr (es, "vpn_gateway", rl->spec.remote_endpoint, -1); @@ -1343,15 +1344,10 @@ add_route (struct route *r,    status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route add command failed");  #elif defined (TARGET_ANDROID) +  struct buffer out = alloc_buf_gc (64, &gc); -    struct user_pass up;     -    struct buffer out = alloc_buf_gc (64, &gc); - -    buf_printf (&out, "%s %s", network, netmask); - -    strcpy(up.username, buf_bptr(&out)); -    management_query_user_pass(management, &up , "ROUTE", GET_USER_PASS_NEED_OK,(void*) 0); - +  buf_printf (&out, "%s %s", network, netmask); +  management_android_control (management, "ROUTE", buf_bptr(&out));  #elif defined (WIN32)    { @@ -1628,13 +1624,11 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla    status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 add command failed");  #elif defined (TARGET_ANDROID) -    struct user_pass up;          struct buffer out = alloc_buf_gc (64, &gc); -     +      buf_printf (&out, "%s/%d", network, r6->netbits); -     -    strcpy(up.username, buf_bptr(&out)); -    management_query_user_pass(management, &up , "ROUTE6", GET_USER_PASS_NEED_OK,(void*) 0); + +    management_android_control (management, "ROUTE6", buf_bptr(&out));  #elif defined (WIN32) diff --git a/openvpn/src/openvpn/snappy.c b/openvpn/src/openvpn/snappy.c new file mode 100644 index 00000000..24440bae --- /dev/null +++ b/openvpn/src/openvpn/snappy.c @@ -0,0 +1,189 @@ +/* + *  OpenVPN -- An application to securely tunnel IP networks + *             over a single UDP port, with support for SSL/TLS-based + *             session authentication and key exchange, + *             packet encryption, packet authentication, and + *             packet compression. + * + *  Copyright (C) 2002-2012 OpenVPN Technologies, Inc. <sales@openvpn.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License version 2 + *  as published by the Free Software Foundation. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program (see the file COPYING included with this + *  distribution); if not, write to the Free Software Foundation, Inc., + *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#include "syshead.h" + +#if defined(ENABLE_SNAPPY) + +#include "snappy-c.h" + +#include "comp.h" +#include "error.h" +#include "otime.h" + +#include "memdbg.h" + +/* Initial command byte to tell our peer if we compressed */ +#define SNAPPY_COMPRESS_BYTE 0x68 + +static void +snap_compress_init (struct compress_context *compctx) +{ +  msg (D_INIT_MEDIUM, "Snappy compression initializing"); +  ASSERT(compctx->flags & COMP_F_SWAP); +} + +static void +snap_compress_uninit (struct compress_context *compctx) +{ +} + +static void +snap_compress (struct buffer *buf, struct buffer work, +	       struct compress_context *compctx, +	       const struct frame* frame) +{ +  snappy_status status; +  bool compressed = false; + +  if (buf->len <= 0) +    return; + +  /* +   * In order to attempt compression, length must be at least COMPRESS_THRESHOLD. +   */ +  if (buf->len >= COMPRESS_THRESHOLD) +    { +      const size_t ps = PAYLOAD_SIZE (frame); +      size_t zlen = ps + COMP_EXTRA_BUFFER (ps); + +      ASSERT (buf_init (&work, FRAME_HEADROOM (frame))); +      ASSERT (buf_safe (&work, zlen)); + +      if (buf->len > ps) +	{ +	  dmsg (D_COMP_ERRORS, "Snappy compression buffer overflow"); +	  buf->len = 0; +	  return; +	} + +      status = snappy_compress((const char *)BPTR(buf), (size_t)BLEN(buf), (char *)BPTR(&work), &zlen); +      if (status != SNAPPY_OK) +	{ +	  dmsg (D_COMP_ERRORS, "Snappy compression error: %d", status); +	  buf->len = 0; +	  return; +	} + +      ASSERT (buf_safe (&work, zlen)); +      work.len = zlen; +      compressed = true; + +      dmsg (D_COMP, "Snappy compress %d -> %d", buf->len, work.len); +      compctx->pre_compress += buf->len; +      compctx->post_compress += work.len; +    } + +  /* did compression save us anything? */ +  { +    uint8_t comp_head_byte = NO_COMPRESS_BYTE_SWAP; +    if (compressed && work.len < buf->len) +      { +	*buf = work; +	comp_head_byte = SNAPPY_COMPRESS_BYTE; +      } + +    { +      uint8_t *head = BPTR (buf); +      uint8_t *tail  = BEND (buf); +      ASSERT (buf_safe (buf, 1)); +      ++buf->len; + +      /* move head byte of payload to tail */ +      *tail = *head; +      *head = comp_head_byte; +    } +  } +} + +static void +snap_decompress (struct buffer *buf, struct buffer work, +		 struct compress_context *compctx, +		 const struct frame* frame) +{ +  size_t zlen = EXPANDED_SIZE (frame); +  snappy_status status; +  uint8_t c;		/* flag indicating whether or not our peer compressed */ + +  if (buf->len <= 0) +    return; + +  ASSERT (buf_init (&work, FRAME_HEADROOM (frame))); + +  /* do unframing/swap (assumes buf->len > 0) */ +  { +    uint8_t *head = BPTR (buf); +    c = *head; +    --buf->len; +    *head = *BEND (buf); +  } + +  if (c == SNAPPY_COMPRESS_BYTE)	/* packet was compressed */ +    { +      ASSERT (buf_safe (&work, zlen)); +      status = snappy_uncompress((const char *)BPTR(buf), (size_t)BLEN(buf), (char *)BPTR(&work), &zlen); +      if (status != SNAPPY_OK) +	{ +	  dmsg (D_COMP_ERRORS, "Snappy decompression error: %d", status); +	  buf->len = 0; +	  return; +	} + +      ASSERT (buf_safe (&work, zlen)); +      work.len = zlen; + +      dmsg (D_COMP, "Snappy decompress %d -> %d", buf->len, work.len); +      compctx->pre_decompress += buf->len; +      compctx->post_decompress += work.len; + +      *buf = work; +    } +  else if (c == NO_COMPRESS_BYTE_SWAP)	/* packet was not compressed */ +    { +      ; +    } +  else +    { +      dmsg (D_COMP_ERRORS, "Bad Snappy decompression header byte: %d", c); +      buf->len = 0; +    } +} + +const struct compress_alg snappy_alg = { +  "snappy", +  snap_compress_init, +  snap_compress_uninit, +  snap_compress, +  snap_decompress +}; + +#else +static void dummy(void) {} +#endif /* ENABLE_SNAPPY */ diff --git a/openvpn/src/openvpn/snappy.h b/openvpn/src/openvpn/snappy.h new file mode 100644 index 00000000..361a6317 --- /dev/null +++ b/openvpn/src/openvpn/snappy.h @@ -0,0 +1,39 @@ +/* + *  OpenVPN -- An application to securely tunnel IP networks + *             over a single UDP port, with support for SSL/TLS-based + *             session authentication and key exchange, + *             packet encryption, packet authentication, and + *             packet compression. + * + *  Copyright (C) 2002-2012 OpenVPN Technologies, Inc. <sales@openvpn.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License version 2 + *  as published by the Free Software Foundation. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program (see the file COPYING included with this + *  distribution); if not, write to the Free Software Foundation, Inc., + *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef OPENVPN_SNAPPY_H +#define OPENVPN_SNAPPY_H + +#if defined(ENABLE_SNAPPY) + +#include "buffer.h" + +extern const struct compress_alg snappy_alg; + +struct snappy_workspace +{ +}; + +#endif /* ENABLE_SNAPPY */ +#endif diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c index 83af046f..af790630 100644 --- a/openvpn/src/openvpn/socket.c +++ b/openvpn/src/openvpn/socket.c @@ -172,7 +172,7 @@ openvpn_getaddrinfo (unsigned int flags,    CLEAR(hints);    hints.ai_family = ai_family;    hints.ai_flags = AI_NUMERICHOST; -  hints.ai_socktype = SOCK_STREAM; +    if(flags & GETADDR_PASSIVE)        hints.ai_flags |= AI_PASSIVE; @@ -697,20 +697,19 @@ create_socket (struct link_socket *sock)  #ifdef TARGET_ANDROID  static void protect_fd_nonlocal (int fd, struct sockaddr* addr)  { -    if (addr_local (addr)) { -        msg(M_DEBUG, "Address is local, not protecting socket fd %d", fd); -        return; -    } -     -    struct user_pass up; -    strcpy(up.username ,__func__); -    management->connection.fdtosend = fd; -    msg(M_DEBUG, "Protecting socket fd %d", fd); -    management_query_user_pass(management, &up , "PROTECTFD", GET_USER_PASS_NEED_OK,(void*) 0); +  /* pass socket FD to management interface to pass on to VPNService API +   * as "protected socket" (exempt from being routed into tunnel) +   */ +  if (addr_local (addr)) { +    msg(M_DEBUG, "Address is local, not protecting socket fd %d", fd); +    return; +  } +  msg(M_DEBUG, "Protecting socket fd %d", fd); +  management->connection.fdtosend = fd; +  management_android_control (management, "PROTECTFD", __func__);  }  #endif -      /*   * Functions used for establishing a TCP stream connection. @@ -933,10 +932,12 @@ openvpn_connect (socket_descriptor_t sd,  {    int status = 0; +#ifdef TARGET_ANDROID +  protect_fd_nonlocal(sd, remote); +#endif +  #ifdef CONNECT_NONBLOCK    set_nonblock (sd); - -  protect_fd_nonlocal(sd, remote);    status = connect (sd, remote, af_addr_size(remote->sa_family));    if (status)      status = openvpn_errno (); @@ -1786,7 +1787,9 @@ link_socket_init_phase2 (struct link_socket *sock,                phase2_socks_client (sock, sig_info);  #endif              } +#ifdef TARGET_ANDROID            protect_fd_nonlocal (sock->sd, &sock->info.lsa->actual.dest.addr.sa); +#endif          }        if (sig_info && sig_info->signal_received) @@ -2772,7 +2775,7 @@ link_socket_read_udp_posix (struct link_socket *sock,    ASSERT (buf_safe (buf, maxsize));  #if ENABLE_IP_PKTINFO    /* Both PROTO_UDPv4 and PROTO_UDPv6 */ -  if (proto_is_udp(sock->info.proto) && sock->sockflags & SF_USE_IP_PKTINFO) +  if (sock->info.proto == PROTO_UDP && sock->sockflags & SF_USE_IP_PKTINFO)      fromlen = link_socket_read_udp_posix_recvmsg (sock, buf, maxsize, from);    else  #endif @@ -2919,7 +2922,7 @@ socket_recv_queue (struct link_socket *sock, int maxsize)        if (proto_is_udp(sock->info.proto))  	{  	  sock->reads.addr_defined = true; -	  if (sock->info.proto == PROTO_UDPv6) +	  if (sock->info.af == AF_INET)  	    sock->reads.addrlen = sizeof (sock->reads.addr6);  	  else  	    sock->reads.addrlen = sizeof (sock->reads.addr); @@ -3018,7 +3021,7 @@ socket_send_queue (struct link_socket *sock, struct buffer *buf, const struct li  	{  	  /* set destination address for UDP writes */  	  sock->writes.addr_defined = true; -	  if (sock->info.proto == PROTO_UDPv6) +	  if (sock->info.af == AF_INET)  	    {  	      sock->writes.addr6 = to->dest.addr.in6;  	      sock->writes.addrlen = sizeof (sock->writes.addr6); diff --git a/openvpn/src/openvpn/socket.h b/openvpn/src/openvpn/socket.h index 5b7a26a9..2b134486 100644 --- a/openvpn/src/openvpn/socket.h +++ b/openvpn/src/openvpn/socket.h @@ -673,6 +673,20 @@ addrlist_match (const struct openvpn_sockaddr *a1, const struct addrinfo *addrli    return false;  } +static inline in_addr_t +addr_host (const struct openvpn_sockaddr *addr) +{ +  /*  +   * "public" addr returned is checked against ifconfig for +   * possible clash: non sense for now given +   * that we do ifconfig only IPv4 +   */ +  if(addr->addr.sa.sa_family != AF_INET) +    return 0; +  return ntohl (addr->addr.in4.sin_addr.s_addr); +} + +  static inline bool  addrlist_port_match (const struct openvpn_sockaddr *a1, const struct addrinfo *a2)  { diff --git a/openvpn/src/openvpn/ssl.c b/openvpn/src/openvpn/ssl.c index 7e261e75..9ca409f1 100644 --- a/openvpn/src/openvpn/ssl.c +++ b/openvpn/src/openvpn/ssl.c @@ -1775,68 +1775,66 @@ push_peer_info(struct buffer *buf, struct tls_session *session)    bool ret = false;  #ifdef ENABLE_PUSH_PEER_INFO -  { -    struct env_set *es = session->opt->es; -    struct env_item *e; -    struct buffer out = alloc_buf_gc (512*3, &gc); +  if (session->opt->push_peer_info) /* write peer info */ +    { +      struct env_set *es = session->opt->es; +      struct env_item *e; +      struct buffer out = alloc_buf_gc (512*3, &gc); -    /* push version */ -    buf_printf (&out, "IV_VER=%s\n", PACKAGE_VERSION); +      /* push version */ +      buf_printf (&out, "IV_VER=%s\n", PACKAGE_VERSION); -    /* push platform */ +      /* push platform */  #if defined(TARGET_LINUX) -    buf_printf (&out, "IV_PLAT=linux\n"); +      buf_printf (&out, "IV_PLAT=linux\n");  #elif defined(TARGET_SOLARIS) -    buf_printf (&out, "IV_PLAT=solaris\n"); +      buf_printf (&out, "IV_PLAT=solaris\n");  #elif defined(TARGET_OPENBSD) -    buf_printf (&out, "IV_PLAT=openbsd\n"); +      buf_printf (&out, "IV_PLAT=openbsd\n");  #elif defined(TARGET_DARWIN) -    buf_printf (&out, "IV_PLAT=mac\n"); +      buf_printf (&out, "IV_PLAT=mac\n");  #elif defined(TARGET_NETBSD) -    buf_printf (&out, "IV_PLAT=netbsd\n"); +      buf_printf (&out, "IV_PLAT=netbsd\n");  #elif defined(TARGET_FREEBSD) -    buf_printf (&out, "IV_PLAT=freebsd\n"); +      buf_printf (&out, "IV_PLAT=freebsd\n");  #elif defined(TARGET_ANDROID) -    buf_printf (&out, "IV_PLAT=android\n"); +      buf_printf (&out, "IV_PLAT=android\n");  #elif defined(WIN32) -    buf_printf (&out, "IV_PLAT=win\n"); +      buf_printf (&out, "IV_PLAT=win\n");  #endif -    /* push compression status */ +      /* push mac addr */ +      { +	struct route_gateway_info rgi; +	get_default_gateway (&rgi); +	if (rgi.flags & RGI_HWADDR_DEFINED) +	  buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc)); +      } + +      /* push compression status */  #ifdef USE_COMP -    comp_generate_peer_info_string(&session->opt->comp_options, &out); +      comp_generate_peer_info_string(&session->opt->comp_options, &out);  #endif -    if (session->opt->push_peer_info) -      { -	/* push mac addr */ +      /* push env vars that begin with UV_ */ +      for (e=es->list; e != NULL; e=e->next)  	{ -	  struct route_gateway_info rgi; -	  get_default_gateway (&rgi); -	  if (rgi.flags & RGI_HWADDR_DEFINED) -	    buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc)); +	  if (e->string) +	    { +	      if (!strncmp(e->string, "UV_", 3) && buf_safe(&out, strlen(e->string)+1)) +		buf_printf (&out, "%s\n", e->string); +	    }  	} -	/* push env vars that begin with UV_ */ -	for (e=es->list; e != NULL; e=e->next) -	  { -	    if (e->string) -	      { -		if (!strncmp(e->string, "UV_", 3) && buf_safe(&out, strlen(e->string)+1)) -		  buf_printf (&out, "%s\n", e->string); -	      } -	  } -      } - -    if (!write_string(buf, BSTR(&out), -1)) -      goto error; -  } -#else -  { -    if (!write_empty_string (buf)) /* no peer info */ -      goto error; -  } +      if (!write_string(buf, BSTR(&out), -1)) +	goto error; +    } +  else  #endif +    { +      if (!write_empty_string (buf)) /* no peer info */ +	goto error; +    }    ret = true;   error: diff --git a/openvpn/src/openvpn/ssl_openssl.c b/openvpn/src/openvpn/ssl_openssl.c index 79cc056e..c1b19dc2 100644 --- a/openvpn/src/openvpn/ssl_openssl.c +++ b/openvpn/src/openvpn/ssl_openssl.c @@ -232,7 +232,7 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)            // %.*s format specifier expects length of type int, so guarantee            // that length is small enough and cast to int.            msg (M_WARN, "No valid translation found for TLS cipher '%.*s'", -              (int) MIN(current_cipher_len, 256), current_cipher); +                 constrain_int(current_cipher_len, 0, 256), current_cipher);          }        else  	{ diff --git a/openvpn/src/openvpn/syshead.h b/openvpn/src/openvpn/syshead.h index 2be11159..df6927de 100644 --- a/openvpn/src/openvpn/syshead.h +++ b/openvpn/src/openvpn/syshead.h @@ -399,13 +399,6 @@  #endif  /* - * do we have the MIN() macro? - */ -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - -/*   * Do we have the capability to report extended socket errors?   */  #if defined(HAVE_LINUX_TYPES_H) && defined(HAVE_LINUX_ERRQUEUE_H) && defined(HAVE_SOCK_EXTENDED_ERR) && defined(HAVE_MSGHDR) && defined(HAVE_CMSGHDR) && defined(CMSG_FIRSTHDR) && defined(CMSG_NXTHDR) && defined(IP_RECVERR) && defined(MSG_ERRQUEUE) && defined(SOL_IP) && defined(HAVE_IOVEC) diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c index d7d53a78..98cb16f3 100644 --- a/openvpn/src/openvpn/tun.c +++ b/openvpn/src/openvpn/tun.c @@ -773,39 +773,33 @@ do_ifconfig (struct tuntap *tt,  #endif /*ENABLE_IPROUTE*/  #elif defined(TARGET_ANDROID) -         -         -        if (do_ipv6) { -            struct user_pass up6;     -            struct buffer out6 = alloc_buf_gc (64, &gc); -            buf_printf (&out6, "%s/%d", ifconfig_ipv6_local,tt->netbits_ipv6); -            strcpy(up6.username, buf_bptr(&out6)); -            management_query_user_pass(management, &up6 , "IFCONFIG6", GET_USER_PASS_NEED_OK,(void*) 0); -        } -        struct user_pass up;     -        struct buffer out = alloc_buf_gc (64, &gc); -        char* top; -        switch(tt->topology) { -            case TOP_NET30: -                top = "net30"; -                break; -            case TOP_P2P: -                top="p2p"; -                break; -            case TOP_SUBNET: -                top="subnet"; -                break; -            default: -                top="undef"; -        } -         -        buf_printf (&out, "%s %s %d %s", ifconfig_local, ifconfig_remote_netmask, tun_mtu,top); -        strcpy(up.username, buf_bptr(&out)); -        management_query_user_pass(management, &up , "IFCONFIG", GET_USER_PASS_NEED_OK,(void*) 0); +      if (do_ipv6) { +          struct buffer out6 = alloc_buf_gc (64, &gc); +          buf_printf (&out6, "%s/%d", ifconfig_ipv6_local,tt->netbits_ipv6); +          management_android_control(management, "IFCONFIG6",buf_bptr(&out6)); +      } +      struct buffer out = alloc_buf_gc (64, &gc); + +      char* top; +      switch(tt->topology) { +      case TOP_NET30: +          top="net30"; +          break; +      case TOP_P2P: +          top="p2p"; +          break; +      case TOP_SUBNET: +          top="subnet"; +          break; +      default: +          top="undef"; +      } + +      buf_printf (&out, "%s %s %d %s", ifconfig_local, ifconfig_remote_netmask, tun_mtu, top); +      management_android_control (management, "IFCONFIG", buf_bptr(&out)); -          #elif defined(TARGET_SOLARIS)        /* Solaris 2.6 (and 7?) cannot set all parameters in one go... @@ -1414,33 +1408,33 @@ close_tun_generic (struct tuntap *tt)  void  open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)  { -    int i; -    struct user_pass up; -    struct gc_arena gc = gc_new (); -     -    for (i = 0; i < tt->options.dns_len; ++i) { -        strcpy(up.username, print_in_addr_t(tt->options.dns[i], 0, &gc)); -        management_query_user_pass(management, &up , "DNSSERVER", GET_USER_PASS_NEED_OK,(void*) 0); -    } +#define ANDROID_TUNNAME "vpnservice-tun" +  int i; +  struct user_pass up; +  struct gc_arena gc = gc_new (); +  bool opentun; -    if(tt->options.domain) { -        strcpy(up.username , tt->options.domain); -        management_query_user_pass(management, &up , "DNSDOMAIN", GET_USER_PASS_NEED_OK,(void*) 0); -    } -     -    strcpy(up.username , dev); -    management_query_user_pass(management, &up , "OPENTUN", GET_USER_PASS_NEED_OK,(void*) 0); +  for (i = 0; i < tt->options.dns_len; ++i) { +    management_android_control (management, "DNSSERVER", +                                print_in_addr_t(tt->options.dns[i], 0, &gc)); +  } -    tt->fd = management->connection.lastfdreceived; -    management->connection.lastfdreceived=-1; -     -    if( (tt->fd < 0) || ! (strcmp("ok",up.password)==0)) { -        msg (M_ERR, "ERROR: Cannot open TUN"); -    } -    /* Set the actual name to a dummy name to enable scripts */ -    tt->actual_name = (char *) malloc(32); -    strncpy(tt->actual_name, "vpnservice-tun",32); -    gc_free (&gc); +  if(tt->options.domain) +    management_android_control (management, "DNSDOMAIN", tt->options.domain); + +  opentun = management_android_control (management, "OPENTUN", dev); + +  /* Pick up the fd from management interface after calling the OPENTUN command */ +  tt->fd = management->connection.lastfdreceived; +  management->connection.lastfdreceived=-1; + +  /* Set the actual name to a dummy name */ +  tt->actual_name = string_alloc (ANDROID_TUNNAME, NULL); + +  if ((tt->fd < 0) || !opentun) +    msg (M_ERR, "ERROR: Cannot open TUN"); + +  gc_free (&gc);  }  void diff --git a/openvpn/src/openvpn/win32.c b/openvpn/src/openvpn/win32.c index 2db96a8d..178e2c35 100644 --- a/openvpn/src/openvpn/win32.c +++ b/openvpn/src/openvpn/win32.c @@ -879,7 +879,10 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i            start_info.dwFlags = STARTF_USESHOWWINDOW;            start_info.wShowWindow = SW_HIDE; -          if (CreateProcessW (cmd, cl, NULL, NULL, FALSE, 0, env, NULL, &start_info, &proc_info)) +          /* this allows console programs to run, and is ignored otherwise */ +          DWORD proc_flags = CREATE_NO_WINDOW; + +          if (CreateProcessW (cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info, &proc_info))              {                DWORD exit_status = 0;                CloseHandle (proc_info.hThread); diff --git a/openvpn/version.m4 b/openvpn/version.m4 index 1ea1c32f..376661f7 100644 --- a/openvpn/version.m4 +++ b/openvpn/version.m4 @@ -1,7 +1,7 @@  dnl define the OpenVPN version  define([PRODUCT_NAME], [OpenVPN])  define([PRODUCT_TARNAME], [openvpn]) -define([PRODUCT_VERSION], [2.3_master]) +define([PRODUCT_VERSION], [2.3_git])  define([PRODUCT_BUGREPORT], [openvpn-users@lists.sourceforge.net])  define([PRODUCT_VERSION_RESOURCE], [2,3,0,0])  dnl define the TAP version | 
