diff options
| -rw-r--r-- | openvpn/.gitignore | 1 | ||||
| -rw-r--r-- | openvpn/configure.ac | 8 | ||||
| -rw-r--r-- | openvpn/doc/openvpn.8 | 20 | ||||
| -rw-r--r-- | openvpn/src/openvpn/forward-inline.h | 1 | ||||
| -rw-r--r-- | openvpn/src/openvpn/init.c | 20 | ||||
| -rw-r--r-- | openvpn/src/openvpn/manage.c | 27 | ||||
| -rw-r--r-- | openvpn/src/openvpn/manage.h | 5 | ||||
| -rw-r--r-- | openvpn/src/openvpn/options.c | 26 | ||||
| -rw-r--r-- | openvpn/src/openvpn/options.h | 1 | ||||
| -rw-r--r-- | openvpn/src/openvpn/proxy.c | 86 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ps.c | 4 | ||||
| -rw-r--r-- | openvpn/src/openvpn/socket.c | 347 | ||||
| -rw-r--r-- | openvpn/src/openvpn/socket.h | 36 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl.c | 3 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl_openssl.c | 27 | ||||
| -rw-r--r-- | openvpn/src/openvpn/tun.c | 64 | 
16 files changed, 390 insertions, 286 deletions
| diff --git a/openvpn/.gitignore b/openvpn/.gitignore index a04afff7..3a2f3842 100644 --- a/openvpn/.gitignore +++ b/openvpn/.gitignore @@ -54,3 +54,4 @@ tests/t_client.sh  tests/t_client-*-20??????-??????/  src/openvpn/openvpn  config-version.h +nbproject diff --git a/openvpn/configure.ac b/openvpn/configure.ac index 65c639c5..b181f6d6 100644 --- a/openvpn/configure.ac +++ b/openvpn/configure.ac @@ -754,7 +754,9 @@ PKG_CHECK_MODULES(  		[  			have_openssl_ssl="yes"  			OPENSSL_SSL_LIBS="-lssl" -		] +		], +		[], +		[-lcrypto]  	)]  ) @@ -812,13 +814,13 @@ if test "${with_crypto_library}" = "polarssl" ; then  #include <polarssl/version.h>  			]],  			[[ -#if POLARSSL_VERSION_NUMBER < 0x01020500 +#if POLARSSL_VERSION_NUMBER < 0x01020A00 || POLARSSL_VERSION_NUMBER >= 0x01030000  #error invalid version  #endif  			]]  		)],  		[AC_MSG_RESULT([ok])], -		[AC_MSG_ERROR([PolarSSL 1.2.5 or newer required])] +		[AC_MSG_ERROR([PolarSSL 1.2.x required and must be 1.2.10 or later])]  	)  	polarssl_with_pkcs11="no" diff --git a/openvpn/doc/openvpn.8 b/openvpn/doc/openvpn.8 index 55152c1c..fba477ba 100644 --- a/openvpn/doc/openvpn.8 +++ b/openvpn/doc/openvpn.8 @@ -221,6 +221,9 @@ options.  indicates the protocol to use when connecting with the  remote, and may be "tcp" or "udp". +For forcing IPv4 or IPv6 connection suffix tcp or udp  +with 4/6 like udp4/udp6/tcp4/tcp6. +  The client will move on to the next host in the list,  in the event of connection failure.  Note that at any given time, the OpenVPN client @@ -553,19 +556,22 @@ Set HTTP "User-Agent" string to  .B user-agent.  .B CUSTOM\-HEADER name content \-\- -Adds the custom Header with  +Adds the custom Header with  .B name -as name and  +as name and  .B content  as the content of the custom HTTP header.  .\"*********************************************************  .TP -.B \-\-socks-proxy server [port] +.B \-\-socks-proxy server [port] [authfile]  Connect to remote host through a Socks5 proxy at address  .B server  and port  .B port  (default=1080). +.B authfile +(optional) is a file containing a username and password on 2 lines, or +"stdin" to prompt from console.  .\"*********************************************************  .TP  .B \-\-socks-proxy-retry @@ -678,7 +684,7 @@ TCP/UDP port number or name for bind.  TCP/UDP port number or name for remote.  .\"*********************************************************  .TP -.B \-\-bind +.B \-\-bind [ipv6only]  Bind to local address and port. This is the default unless any of   .B \-\-proto tcp-client  , @@ -686,6 +692,12 @@ Bind to local address and port. This is the default unless any of  or  .B \-\-socks-proxy  are used. + +If the  +.B \-\-ipv6only +keyword is present OpenVPN will bind only to IPv6 (as oposed +to IPv6 and IPv4) when a IPv6 socket is opened. +  .\"*********************************************************  .TP  .B \-\-nobind diff --git a/openvpn/src/openvpn/forward-inline.h b/openvpn/src/openvpn/forward-inline.h index 7eb480dd..5853ce29 100644 --- a/openvpn/src/openvpn/forward-inline.h +++ b/openvpn/src/openvpn/forward-inline.h @@ -228,7 +228,6 @@ context_reschedule_sec (struct context *c, int sec)  static inline struct link_socket_info *  get_link_socket_info (struct context *c)  { -    if (c->c2.link_socket_info)      return c->c2.link_socket_info;    else diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c index 8cd136d5..7c9bf048 100644 --- a/openvpn/src/openvpn/init.c +++ b/openvpn/src/openvpn/init.c @@ -284,6 +284,7 @@ static void  init_connection_list (struct context *c)  {    struct connection_list *l = c->options.connection_list; +    l->current = -1;    if (c->options.remote_random)      { @@ -1425,10 +1426,10 @@ do_open_tun (struct context *c)  #ifdef TARGET_ANDROID        /* If we emulate persist-tun on android we still have to open a new tun and -         then close the old */ +       * then close the old */        int oldtunfd=-1;        if (c->c1.tuntap) -          oldtunfd = c->c1.tuntap->fd; +	oldtunfd = c->c1.tuntap->fd;  #endif        /* initialize (but do not open) tun/tap object */ @@ -1462,14 +1463,14 @@ do_open_tun (struct context *c)          do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,                    c->c1.tuntap, c->plugins, c->c2.es);        } - +#ifdef TARGET_ANDROID +	/* Store the old fd inside the fd so open_tun can use it */ +	c->c1.tuntap->fd = oldtunfd; +#endif        /* 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) -        close(oldtunfd); -#endif +        /* set the hardware address */        if (c->options.lladdr)  	  set_lladdr(c->c1.tuntap->actual_name, c->options.lladdr, c->c2.es); @@ -1580,7 +1581,7 @@ do_close_tun (struct context *c, bool force)  	  /* delete any routes we added */  	  if (c->c1.route_list || c->c1.route_ipv6_list ) -            { +           {                run_up_down (c->options.route_predown_script,                             c->plugins,                             OPENVPN_PLUGIN_ROUTE_PREDOWN, @@ -2688,7 +2689,8 @@ do_init_socket_1 (struct context *c, const int mode)  			   c->options.ce.remote,  			   c->options.ce.remote_port,  			   c->options.ce.proto, -         c->options.ce.af, +			   c->options.ce.af, +			   c->options.ce.bind_ipv6_only,  			   mode,  			   c->c2.accept_from,  #ifdef ENABLE_HTTP_PROXY diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c index 23e76527..8217ead2 100644 --- a/openvpn/src/openvpn/manage.c +++ b/openvpn/src/openvpn/manage.c @@ -1570,7 +1570,7 @@ man_listen (struct management *man)  	{  	  man->connection.sd_top = create_socket_tcp (AF_INET);  	  socket_bind (man->connection.sd_top, man->settings.local, -                       AF_INET, "MANAGEMENT"); +                       AF_INET, "MANAGEMENT", true);  	}        /* @@ -1864,6 +1864,31 @@ bool management_android_control (struct management *man, const char *command, co    management_query_user_pass(management, &up , command, GET_USER_PASS_NEED_OK,(void*) 0);    return strcmp ("ok", up.password)==0;  } + +/* + * In Android 4.4 it is not possible to open a new tun device and then close the + * old tun device without breaking the whole VPNService stack until the device + * is reported. This management method ask the UI what method should be taken to + * ensure the optimal solution for the situation + */ +int managment_android_persisttun_action (struct management *man) +{ +  struct user_pass up; +  CLEAR(up); +  strcpy(up.username,"tunmethod"); +  management_query_user_pass(management, &up , "PERSIST_TUN_ACTION", +			     GET_USER_PASS_NEED_OK,(void*) 0); +  if (!strcmp("NOACTION", up.password)) +    return ANDROID_KEEP_OLD_TUN; +  else if (!strcmp ("OPEN_AFTER_CLOSE", up.password)) +    return ANDROID_OPEN_AFTER_CLOSE; +  else if (!strcmp ("OPEN_BEFORE_CLOSE", up.password)) +    return ANDROID_OPEN_BEFORE_CLOSE; +  else +    ASSERT (0); +} + +  #endif  static int diff --git a/openvpn/src/openvpn/manage.h b/openvpn/src/openvpn/manage.h index dc3ade10..f5a621b7 100644 --- a/openvpn/src/openvpn/manage.h +++ b/openvpn/src/openvpn/manage.h @@ -378,6 +378,11 @@ bool management_query_user_pass (struct management *man,  #ifdef TARGET_ANDROID  bool management_android_control (struct management *man, const char *command, const char *msg); + +#define ANDROID_KEEP_OLD_TUN 1 +#define ANDROID_OPEN_AFTER_CLOSE 2 +#define ANDROID_OPEN_BEFORE_CLOSE 3 +int managment_android_persisttun_action (struct management *man);  #endif  bool management_should_daemonize (struct management *man); diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c index 66fb8962..89a5888d 100644 --- a/openvpn/src/openvpn/options.c +++ b/openvpn/src/openvpn/options.c @@ -780,6 +780,7 @@ init_options (struct options *o, const bool init_gc)    o->topology = TOP_NET30;    o->ce.proto = PROTO_UDP;    o->ce.af = AF_UNSPEC; +  o->ce.bind_local=false;    o->ce.connect_retry_seconds = 5;    o->ce.connect_timeout = 10;    o->connect_retry_max = 0; @@ -2037,8 +2038,12 @@ options_postprocess_verify_ce (const struct options *options, const struct conne        if (ce->socks_proxy_server)  	msg (M_USAGE, "--socks-proxy cannot be used with --mode server");  #endif -      if (options->connection_list) -	msg (M_USAGE, "<connection> cannot be used with --mode server"); +      /* <connection> blocks force to have a remote embedded, so we check for the  +       * --remote and bail out if it  is present */ +       if (options->connection_list->len >1 || +                  options->connection_list->array[0]->remote) +          msg (M_USAGE, "<connection> cannot be used with --mode server"); +  #if 0        if (options->tun_ipv6)  	msg (M_USAGE, "--tun-ipv6 cannot be used with --mode server"); @@ -4446,14 +4451,14 @@ add_option (struct options *options,  	  if (p[3])  	    {  	      const int proto = ascii2proto (p[3]); -        const sa_family_t af = ascii2af (p[3]); +	      const sa_family_t af = ascii2af (p[3]);  	      if (proto < 0)  		{  		  msg (msglevel, "remote: bad protocol associated with host %s: '%s'", p[1], p[3]);  		  goto err;  		}  	      re.proto = proto; -        re.af = af; +	      re.af = af;  	    }  	}        if (permission_mask & OPT_P_GENERAL) @@ -4875,6 +4880,9 @@ add_option (struct options *options,      {        VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);        options->ce.bind_defined = true; +      if (p[1] && streq (p[1], "ipv6only")) +          options->ce.bind_ipv6_only=true; +      }    else if (streq (p[0], "nobind"))      { @@ -5000,10 +5008,10 @@ add_option (struct options *options,        else if ((streq (p[1], "EXT1") || streq(p[1], "EXT2") || streq(p[1], "CUSTOM-HEADER"))  	       && p[2])  	{ -	  /* In the wild patched versions use both EXT1/2 and CUSTOM-HEADER with either two -	   * argument or one */ +	  /* In the wild patched versions use both EXT1/2 and CUSTOM-HEADER +	   * with either two argument or one */ -	  struct http_custom_header *custom_header =NULL; +	  struct http_custom_header *custom_header = NULL;  	  int i;  	  /* Find the first free header */  	  for (i=0; i < MAX_CUSTOM_HTTP_HEADER; i++) { @@ -5014,11 +5022,11 @@ add_option (struct options *options,  	  }  	  if (!custom_header)  	    { -	      msg (msglevel, "Cannot use more than %d http-proxy-option CUSTOM-HEAER : '%s'", MAX_CUSTOM_HTTP_HEADER, p[1]); +	      msg (msglevel, "Cannot use more than %d http-proxy-option CUSTOM-HEADER : '%s'", MAX_CUSTOM_HTTP_HEADER, p[1]);  	    }  	  else  	    { -	      /* We will save p[2] and p[3], the proxy code will detect if  +	      /* We will save p[2] and p[3], the proxy code will detect if  	       * p[3] is NULL */  	      custom_header->name = p[2];  	      custom_header->content = p[3]; diff --git a/openvpn/src/openvpn/options.h b/openvpn/src/openvpn/options.h index 99877da7..4e97a192 100644 --- a/openvpn/src/openvpn/options.h +++ b/openvpn/src/openvpn/options.h @@ -95,6 +95,7 @@ struct connection_entry    const char *remote;    bool remote_float;    bool bind_defined; +  bool bind_ipv6_only;    bool bind_local;    int connect_retry_seconds;    int connect_timeout; diff --git a/openvpn/src/openvpn/proxy.c b/openvpn/src/openvpn/proxy.c index db26994c..f7f06487 100644 --- a/openvpn/src/openvpn/proxy.c +++ b/openvpn/src/openvpn/proxy.c @@ -489,37 +489,50 @@ http_proxy_close (struct http_proxy_info *hp)  }  bool -add_proxy_header (struct http_proxy_info *p, +add_proxy_headers (struct http_proxy_info *p,  		  socket_descriptor_t sd, /* already open to proxy */  		  const char *host,	  /* openvpn server remote */ -		  const char *port	  /* openvpn server port */ +		  const char* port	  /* openvpn server port */  		  )  {    char buf[512];    int i; -  bool hostheadercustom=false; -   -  /* Check if any of the custom headers already provides Host: */ -  i=0; +  bool host_header_sent=false; + +  /* +   * Send custom headers if provided +   * If content is NULL the whole header is in name +   * Also remember if we already sent a Host: header +   */    for  (i=0; i < MAX_CUSTOM_HTTP_HEADER && p->options.custom_headers[i].name;i++)      { -      if( -	 ((!strcasecmp(p->options.custom_headers[i].name, "Host")) &&  -	  (p->options.custom_headers[i].content)) -	 || -	 ((!strncasecmp(p->options.custom_headers[i].name, "Host:", 5)) &&  -	  p->options.custom_headers[i].content == NULL) -	 ) -	hostheadercustom=true; -      i++; +      if (p->options.custom_headers[i].content) +	{ +	  openvpn_snprintf (buf, sizeof(buf), "%s: %s", +			    p->options.custom_headers[i].name, +			    p->options.custom_headers[i].content); +	  if (!strcasecmp(p->options.custom_headers[i].name, "Host")) +	      host_header_sent=true; +	} +      else +	{ +	  openvpn_snprintf (buf, sizeof(buf), "%s", +			    p->options.custom_headers[i].name); +	  if (!strncasecmp(p->options.custom_headers[i].name, "Host:", 5)) +	      host_header_sent=true; +	} + +      msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); +      if (!send_line_crlf (sd, buf)) +	return false;      } -  if (!hostheadercustom)  +  if (!host_header_sent)      { -    openvpn_snprintf (buf, sizeof(buf), "Host: %s", host); -    msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); -    if (!send_line_crlf(sd, buf)) -      return false; +      openvpn_snprintf (buf, sizeof(buf), "Host: %s", host); +      msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); +      if (!send_line_crlf(sd, buf)) +        return false;      }    /* send User-Agent string if provided */ @@ -532,26 +545,6 @@ add_proxy_header (struct http_proxy_info *p,  	return false;      } -  /* -   * Send custom headers if provided -   * If content is NULL whole header is in name -   */ -  for  (i=0; i < MAX_CUSTOM_HTTP_HEADER && p->options.custom_headers[i].name;i++) -    { -      if (p->options.custom_headers[i].content) -	openvpn_snprintf (buf, sizeof(buf), "%s: %s", -			  p->options.custom_headers[i].name, -			  p->options.custom_headers[i].content); -      else -	openvpn_snprintf (buf, sizeof(buf), "%s", -			  p->options.custom_headers[i].name); - -      msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); -      if (!send_line_crlf (sd, buf)) -	return false; -      i++; -    } -    return true;  } @@ -598,9 +591,9 @@ establish_http_proxy_passthru (struct http_proxy_info *p,        /* send HTTP CONNECT message to proxy */        if (!send_line_crlf (sd, buf))  	goto error; -       -      if(!add_proxy_header (p, sd, host, port)) -        goto error; + +      if (!add_proxy_headers (p, sd, host, port)) +	goto error;        /* auth specified? */        switch (p->auth_method) @@ -715,9 +708,8 @@ establish_http_proxy_passthru (struct http_proxy_info *p,            if (!send_line_crlf (sd, buf))              goto error; -                      /* send HOST etc, */ -	  if(!add_proxy_header (p, sd, host, port)) +	  if (!add_proxy_headers (p, sd, host, port))  	    goto error;  	  msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 3"); @@ -826,8 +818,8 @@ establish_http_proxy_passthru (struct http_proxy_info *p,  		goto error;  	      /* send HOST etc, */ -              if(!add_proxy_header (p, sd, host, port)) -                goto error; +	      if (!add_proxy_headers (p, sd, host, port)) +		goto error;  	      /* send digest response */  	      openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", qop=%s, nc=%s, cnonce=\"%s\", response=\"%s\"%s", diff --git a/openvpn/src/openvpn/ps.c b/openvpn/src/openvpn/ps.c index c1868642..a57ac547 100644 --- a/openvpn/src/openvpn/ps.c +++ b/openvpn/src/openvpn/ps.c @@ -408,20 +408,18 @@ proxy_entry_new (struct proxy_connection **list,  		 struct buffer *initial_data,  		 const char *journal_dir)  { -  struct openvpn_sockaddr osaddr;    socket_descriptor_t sd_server;    int status;    struct proxy_connection *pc;    struct proxy_connection *cp;    /* connect to port share server */ -  osaddr.addr.in4 = server_addr;    if ((sd_server = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)      {        msg (M_WARN|M_ERRNO, "PORT SHARE PROXY: cannot create socket");        return false;      } -  status = openvpn_connect (sd_server, &osaddr, 5, NULL); +  status = openvpn_connect (sd_server,(const struct sockaddr*)  &server_addr, 5, NULL);    if (status)      {        msg (M_WARN, "PORT SHARE PROXY: connect to port-share server failed"); diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c index 0898babe..c5f085f8 100644 --- a/openvpn/src/openvpn/socket.c +++ b/openvpn/src/openvpn/socket.c @@ -663,10 +663,9 @@ create_socket (struct link_socket *sock)  {    /* create socket, use information carried over from getaddrinfo */    const int ai_proto = sock->info.lsa->actual.ai_protocol; -  const int ai_family = sock->info.lsa->actual.ai_family; -     -  ASSERT (sock->info.af == AF_UNSPEC  || sock->info.af == ai_family); +  int ai_family = sock->info.lsa->actual.ai_family; +  ASSERT (sock->info.af == AF_UNSPEC  || sock->info.af == ai_family);    if (ai_proto == IPPROTO_UDP)      { @@ -889,7 +888,8 @@ void  socket_bind (socket_descriptor_t sd,               struct addrinfo *local,               int ai_family, -	     const char *prefix) +	     const char *prefix, +             bool ipv6only)  {    struct gc_arena gc = gc_new (); @@ -900,8 +900,11 @@ socket_bind (socket_descriptor_t sd,     * What is the correct way to deal with it?     */ -  ASSERT(local);    struct addrinfo* cur; +  int v6only= ipv6only ? 0: 1; +   +  ASSERT(local); +     /* find the first addrinfo with correct ai_family */    for (cur = local; cur; cur=cur->ai_next) @@ -912,7 +915,14 @@ socket_bind (socket_descriptor_t sd,    if (!cur)        msg (M_FATAL, "%s: Socket bind failed: Addr to bind has no %s record",             prefix, addr_family_name(ai_family)); -     + +  if (ai_family == AF_INET6) +    { +      if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only))) +	{ +	  msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY failed"); +	} +    }    if (bind (sd, cur->ai_addr, cur->ai_addrlen))      {        const int errnum = openvpn_errno (); @@ -1138,19 +1148,20 @@ resolve_bind_local (struct link_socket *sock, const sa_family_t af)    if (!sock->info.lsa->bind_local)      {        int flags = GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | -                   GETADDR_FATAL | GETADDR_PASSIVE; +	GETADDR_FATAL | GETADDR_PASSIVE;        int status; -       +        if(proto_is_dgram(sock->info.proto)) -          flags |= GETADDR_DATAGRAM; -  +	flags |= GETADDR_DATAGRAM; +        /* will return AF_{INET|INET6}from local_host */        status = openvpn_getaddrinfo(flags, sock->local_host, sock->local_port, 0, -                                   NULL, af, &sock->info.lsa->bind_local); +				   NULL, af, &sock->info.lsa->bind_local); +        if(status !=0) { -        msg (M_FATAL, "getaddrinfo() failed for local \"%s:%s\": %s", -             sock->local_host, sock->local_port, -             gai_strerror(status)); +	msg (M_FATAL, "getaddrinfo() failed for local \"%s:%s\": %s", +	     sock->local_host, sock->local_port, +	     gai_strerror(status));        }      } @@ -1165,11 +1176,12 @@ static void bind_local (struct link_socket *sock)  #ifdef ENABLE_SOCKS          if (sock->socks_proxy && sock->info.proto == PROTO_UDP)              socket_bind (sock->ctrl_sd, sock->info.lsa->bind_local, -                         sock->info.lsa->actual.ai_family, "SOCKS"); +                         sock->info.lsa->actual.ai_family, "SOCKS", false);          else  #endif              socket_bind (sock->sd, sock->info.lsa->bind_local, -                         sock->info.lsa->actual.ai_family,  "TCP/UDP"); +                         sock->info.lsa->actual.ai_family, +                         "TCP/UDP", sock->info.bind_ipv6_only);        }  } @@ -1306,11 +1318,12 @@ create_new_socket (struct link_socket* sock)        resolve_bind_local (sock, sock->info.af);    }    resolve_remote (sock, 1, NULL, NULL); +      /*     * In P2P or server mode we must create the socket even when resolving     * the remote site fails/is not specified. */ -  if (sock->info.af && sock->info.lsa->actual.ai_family==0 && sock->bind_local) +  if (sock->info.lsa->actual.ai_family==0 && sock->bind_local)      {        /* Copy sock parameters from bind addr */        set_actual_address (&sock->info.lsa->actual, sock->info.lsa->bind_local); @@ -1321,7 +1334,7 @@ create_new_socket (struct link_socket* sock)    /*      * Create the socket early if socket should be bound     */ -  if (sock->bind_local && sock->info.lsa->actual.ai_family) +  if (sock->bind_local)      {        create_socket (sock); @@ -1339,7 +1352,8 @@ link_socket_init_phase1 (struct link_socket *sock,  			 const char *remote_host,  			 const char *remote_port,  			 int proto, -       sa_family_t af, +			 sa_family_t af, +			 bool bind_ipv6_only,  			 int mode,  			 const struct link_socket *accept_from,  #ifdef ENABLE_HTTP_PROXY @@ -1400,6 +1414,7 @@ link_socket_init_phase1 (struct link_socket *sock,    sock->info.af = af;    sock->info.remote_float = remote_float;    sock->info.lsa = lsa; +  sock->info.bind_ipv6_only = bind_ipv6_only;    sock->info.ipchange_command = ipchange_command;    sock->info.plugins = plugins; @@ -1452,7 +1467,7 @@ link_socket_init_phase1 (struct link_socket *sock,      }    /* bind behavior for TCP server vs. client */ -  if (sock->info.proto == PROTO_TCP_SERVER && sock->info.af==AF_INET) +  if (sock->info.proto == PROTO_TCP_SERVER)      {        if (sock->mode == LS_MODE_TCP_ACCEPT_FROM)  	sock->bind_local = false; @@ -1475,7 +1490,7 @@ link_socket_init_phase1 (struct link_socket *sock,  static  void phase2_inetd (struct link_socket* sock, const struct frame *frame, -                   const char *remote_dynamic, volatile int *signal_received) +		   const char *remote_dynamic, volatile int *signal_received)  {    bool remote_changed = false; @@ -1488,27 +1503,28 @@ void phase2_inetd (struct link_socket* sock, const struct frame *frame,        struct openvpn_sockaddr local_addr;        socklen_t addrlen = sizeof(local_addr);        if (getsockname (sock->sd, &local_addr.addr.sa, &addrlen) == 0) { -        sock->info.lsa->actual.dest.addr.sa.sa_family = local_addr.addr.sa.sa_family; -        dmsg (D_SOCKET_DEBUG, "inetd(%s): using sa_family=%d from getsockname(%d)", -              proto2ascii(sock->info.proto, sock->info.af, false), local_addr.addr.sa.sa_family, -              sock->sd); +	sock->info.lsa->actual.dest.addr.sa.sa_family = local_addr.addr.sa.sa_family; +	dmsg (D_SOCKET_DEBUG, "inetd(%s): using sa_family=%d from getsockname(%d)", +	      proto2ascii(sock->info.proto, sock->info.af, false), +	      local_addr.addr.sa.sa_family, sock->sd);        } else -        msg (M_WARN, "inetd(%s): getsockname(%d) failed, using AF_INET", -             proto2ascii(sock->info.proto, sock->info.af, false), sock->sd); +	msg (M_WARN, "inetd(%s): getsockname(%d) failed, using AF_INET", +	     proto2ascii(sock->info.proto, sock->info.af, false), sock->sd);      }  #else      msg (M_WARN, "inetd(%s): this OS does not provide the getsockname() " -         "function, using AF_INET", -         proto2ascii(sock->info.proto, false)); +	 "function, using AF_INET", +	 proto2ascii(sock->info.proto, false));  #endif      sock->sd =        socket_listen_accept (sock->sd, -                            &sock->info.lsa->actual, -                            remote_dynamic, -                            sock->info.lsa->bind_local, -                            false, -                            sock->inetd == INETD_NOWAIT, -                            signal_received); +			    &sock->info.lsa->actual, +			    remote_dynamic, +			    sock->info.lsa->bind_local, +			    false, +			    sock->inetd == INETD_NOWAIT, +			    signal_received); +    }    ASSERT (!remote_changed);  } @@ -1549,68 +1565,68 @@ linksock_print_addr (struct link_socket *sock)    /* print local address */    {      const int msglevel = (sock->mode == LS_MODE_TCP_ACCEPT_FROM) ? D_INIT_MEDIUM : M_INFO; -     +      if (sock->inetd)        msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, sock->info.af, true));      else if (sock->bind_local)        { -        /* Socket is always bound on the first matching address */ -        struct addrinfo *cur; -        for (cur = sock->info.lsa->bind_local; cur; cur=cur->ai_next) -          { -            if(cur->ai_family == sock->info.lsa->actual.ai_family) -                break; -          } -        ASSERT (cur); -        msg (msglevel, "%s link local (bound): %s", -           proto2ascii (sock->info.proto, sock->info.af, true), -           print_sockaddr(cur->ai_addr,&gc)); +	/* Socket is always bound on the first matching address */ +	struct addrinfo *cur; +	for (cur = sock->info.lsa->bind_local; cur; cur=cur->ai_next) +	  { +	    if(cur->ai_family == sock->info.lsa->actual.ai_family) +		break; +	  } +	ASSERT (cur); +	msg (msglevel, "%s link local (bound): %s", +	   proto2ascii (sock->info.proto, sock->info.af, true), +	   print_sockaddr(cur->ai_addr,&gc));        }      else -        msg (msglevel, "%s link local: (not bound)", -             proto2ascii (sock->info.proto, sock->info.af, true)); -     +	msg (msglevel, "%s link local: (not bound)", +	     proto2ascii (sock->info.proto, sock->info.af, true)); +      /* print active remote address */      msg (msglevel, "%s link remote: %s", -         proto2ascii (sock->info.proto, sock->info.af, true), -         print_link_socket_actual_ex (&sock->info.lsa->actual, -                                      ":", -                                      PS_SHOW_PORT_IF_DEFINED, -                                      &gc)); +	 proto2ascii (sock->info.proto, sock->info.af, true), +	 print_link_socket_actual_ex (&sock->info.lsa->actual, +				      ":", +				      PS_SHOW_PORT_IF_DEFINED, +				      &gc));    }    gc_free(&gc);  }  static void  phase2_tcp_server (struct link_socket *sock, const char *remote_dynamic, -                   volatile int *signal_received) +		   volatile int *signal_received)  {    switch (sock->mode)      {      case LS_MODE_DEFAULT:        sock->sd = socket_listen_accept (sock->sd, -                                       &sock->info.lsa->actual, -                                       remote_dynamic, -                                       sock->info.lsa->bind_local, -                                       true, -                                       false, -                                       signal_received); +				       &sock->info.lsa->actual, +				       remote_dynamic, +				       sock->info.lsa->bind_local, +				       true, +				       false, +				       signal_received);        break;      case LS_MODE_TCP_LISTEN:        socket_do_listen (sock->sd, -                        sock->info.lsa->bind_local->ai_addr, -                        true, -                        false); +			sock->info.lsa->bind_local->ai_addr, +			true, +			false);        break;      case LS_MODE_TCP_ACCEPT_FROM:        sock->sd = socket_do_accept (sock->sd, -                                   &sock->info.lsa->actual, -                                   false); +				   &sock->info.lsa->actual, +				   false);        if (!socket_defined (sock->sd)) -        { -          *signal_received = SIGTERM; -          return; -        } +	{ +	  *signal_received = SIGTERM; +	  return; +	}        tcp_connection_established (&sock->info.lsa->actual);        break;      default: @@ -1624,50 +1640,51 @@ static void  phase2_tcp_client (struct link_socket *sock, struct signal_info *sig_info)  {  #ifdef GENERAL_PROXY_SUPPORT -    bool proxy_retry = false; +  bool proxy_retry = false;  #else -    const bool proxy_retry = false; -#endif -    do { -        socket_connect (&sock->sd, -                        sock->info.lsa, -                        sock->connect_timeout, -                        sig_info); -         -        if (sig_info->signal_received) -            return; -         -        if (false) -            ; +  const bool proxy_retry = false; +#endif +  do { +    socket_connect (&sock->sd, +		    sock->info.lsa, +		    sock->connect_timeout, +		    sig_info); + +    if (sig_info->signal_received) +      return; + +    if (false) +      ;  #ifdef ENABLE_HTTP_PROXY -        else if (sock->http_proxy) -            { -                proxy_retry = establish_http_proxy_passthru (sock->http_proxy, -                                                             sock->sd, -                                                             sock->proxy_dest_host, -                                                             sock->proxy_dest_port, -                                                             &sock->stream_buf.residual, -                                                             &sig_info->signal_received); -            } +    else if (sock->http_proxy) +      { +	proxy_retry = establish_http_proxy_passthru (sock->http_proxy, +						     sock->sd, +						     sock->proxy_dest_host, +						     sock->proxy_dest_port, +						     &sock->stream_buf.residual, +						     &sig_info->signal_received); +      }  #endif  #ifdef ENABLE_SOCKS -        else if (sock->socks_proxy) -            { -                establish_socks_proxy_passthru (sock->socks_proxy, -                                                sock->sd, -                                                sock->proxy_dest_host, -                                                sock->proxy_dest_port, -                                                &sig_info->signal_received); -            } +    else if (sock->socks_proxy) +      { +	establish_socks_proxy_passthru (sock->socks_proxy, +					sock->sd, +					sock->proxy_dest_host, +					sock->proxy_dest_port, +					&sig_info->signal_received); +      }  #endif -        if (proxy_retry) -            { -              /* TODO (schwabe): This code assumes AF_INET for the proxy socket -               * when retrying a connection */ -                openvpn_close_socket (sock->sd); -                sock->sd = create_socket_tcp (AF_INET); -            } -    } while (proxy_retry); +    if (proxy_retry) +      { +	/* TODO (schwabe): This code assumes AF_INET for the proxy socket +	 * when retrying a connection */ +	openvpn_close_socket (sock->sd); +	sock->sd = create_socket_tcp (AF_INET); +      } + +  } while (proxy_retry);  } @@ -1676,44 +1693,43 @@ static void  phase2_socks_client (struct link_socket *sock, struct signal_info *sig_info)  {      socket_connect (&sock->ctrl_sd, -                    sock->info.lsa, -                    sock->connect_timeout, -                    sig_info); -     +		    sock->info.lsa, +		    sock->connect_timeout, +		    sig_info); +      if (sig_info->signal_received) -        return; -     +	return; +       establish_socks_proxy_udpassoc (sock->socks_proxy, -                                    sock->ctrl_sd, -                                    sock->sd, -                                    &sock->socks_relay.dest, -                                    &sig_info->signal_received); -     +				    sock->ctrl_sd, +				    sock->sd, +				    &sock->socks_relay.dest, +				    &sig_info->signal_received); +      if (sig_info->signal_received) -        return; -     +	return; +      sock->remote_host = sock->proxy_dest_host;      sock->remote_port = sock->proxy_dest_port;      sock->did_resolve_remote = false; -     +      addr_zero_host(&sock->info.lsa->actual.dest);      if (sock->info.lsa->remote_list)        { -        freeaddrinfo(sock->info.lsa->remote_list); +	freeaddrinfo(sock->info.lsa->remote_list);  	sock->info.lsa->current_remote = NULL;  	sock->info.lsa->remote_list = NULL;        } -     +      resolve_remote (sock, 1, NULL, &sig_info->signal_received); -      }  #endif  /* finalize socket initialization */  void  link_socket_init_phase2 (struct link_socket *sock, -                         const struct frame *frame, -                         struct signal_info *sig_info) +			 const struct frame *frame, +			 struct signal_info *sig_info)  {    const char *remote_dynamic = NULL;    int sig_save = 0; @@ -1742,71 +1758,66 @@ link_socket_init_phase2 (struct link_socket *sock,      {        phase2_inetd (sock, frame, remote_dynamic,  &sig_info->signal_received);        if (sig_info && sig_info->signal_received) -        goto done; +	goto done;      }    else      {        /* Second chance to resolv/create socket */        resolve_remote (sock, 2, &remote_dynamic,  &sig_info->signal_received); -       +        /* If socket has not already been created create it now */        if (sock->sd == SOCKET_UNDEFINED) -        { -          if (sock->info.lsa->actual.ai_family) -            { -              create_socket (sock); -            } -          else -            { -              msg (M_WARN, "Could not determine IPv4/IPv6 protocol"); -              sig_info->signal_received = SIGUSR1; -              goto done; -            } -           -          if (sock->bind_local) -              bind_local(sock); -        } +	{ +	  if (sock->info.lsa->actual.ai_family) +	    { +	      create_socket (sock); +	    } +	  else +	    { +	      msg (M_WARN, "Could not determine IPv4/IPv6 protocol"); +	      sig_info->signal_received = SIGUSR1; +	      goto done; +	    } + +	  if (sock->bind_local) +	    bind_local(sock); +	} -              if (sig_info && sig_info->signal_received) -        goto done; +	goto done;        if (sock->info.proto == PROTO_TCP_SERVER) -        { -          phase2_tcp_server (sock, remote_dynamic, -                             &sig_info->signal_received); -        } +	{ +	  phase2_tcp_server (sock, remote_dynamic, +			     &sig_info->signal_received); +	}        else if (sock->info.proto == PROTO_TCP_CLIENT) -        { -          phase2_tcp_client (sock, sig_info); -     -        } -      else if (sock->info.proto == PROTO_UDP) -        { +	{ +	  phase2_tcp_client (sock, sig_info); + +	}  #ifdef ENABLE_SOCKS -          if (sock->info.proto == PROTO_UDP && sock->socks_proxy) -            { -              phase2_socks_client (sock, sig_info); +      else if (sock->info.proto == PROTO_UDP && sock->socks_proxy) +	{ +	  phase2_socks_client (sock, sig_info);  #endif -            } +	}  #ifdef TARGET_ANDROID -          protect_fd_nonlocal (sock->sd, &sock->info.lsa->actual.dest.addr.sa); +      protect_fd_nonlocal (sock->sd, &sock->info.lsa->actual.dest.addr.sa);  #endif -        } -        if (sig_info && sig_info->signal_received) -        goto done; +	goto done;      }    phase2_set_socket_flags(sock);    linksock_print_addr(sock); -  +   done:    if (sig_save && sig_info)      {        if (!sig_info->signal_received) -        sig_info->signal_received = sig_save; +	sig_info->signal_received = sig_save;      }  } diff --git a/openvpn/src/openvpn/socket.h b/openvpn/src/openvpn/socket.h index d077a153..4c18b740 100644 --- a/openvpn/src/openvpn/socket.h +++ b/openvpn/src/openvpn/socket.h @@ -118,6 +118,7 @@ struct link_socket_info    bool remote_float;      int proto;                    /* Protocol (PROTO_x defined below) */    sa_family_t af;                       /* Address family like AF_INET, AF_INET6 or AF_UNSPEC*/ +  bool bind_ipv6_only;    int mtu_changed;              /* Set to true when mtu value is changed */  }; @@ -289,7 +290,8 @@ struct link_socket *link_socket_new (void);  void socket_bind (socket_descriptor_t sd,  		  struct addrinfo *local,                    int af_family, -		  const char *prefix); +		  const char *prefix, +                  bool ipv6only);  int openvpn_connect (socket_descriptor_t sd,  		     const struct sockaddr *remote, @@ -308,6 +310,7 @@ link_socket_init_phase1 (struct link_socket *sock,  			 const char *remote_port,  			 int proto,         sa_family_t af, +                         bool bind_ipv6_only,  			 int mode,  			 const struct link_socket *accept_from,  #ifdef ENABLE_HTTP_PROXY @@ -600,14 +603,14 @@ static inline bool  addr_local (const struct sockaddr *addr)  {      if (!addr) -        return false; +	return false;      switch (addr->sa_family) { -        case AF_INET: -            return ((const struct sockaddr_in*)addr)->sin_addr.s_addr == htonl(INADDR_LOOPBACK); -        case AF_INET6: -            return  IN6_IS_ADDR_LOOPBACK(&((const struct sockaddr_in6*)addr)->sin6_addr); -        default: -            return false; +	case AF_INET: +	    return ((const struct sockaddr_in*)addr)->sin_addr.s_addr == htonl(INADDR_LOOPBACK); +	case AF_INET6: +	    return  IN6_IS_ADDR_LOOPBACK(&((const struct sockaddr_in6*)addr)->sin6_addr); +	default: +	    return false;      }  } @@ -853,7 +856,7 @@ link_socket_verify_incoming_addr (struct buffer *buf,  	case AF_INET:  	  if (!link_socket_actual_defined (from_addr))  	    return false; -	  if (info->remote_float || !info->lsa->remote_list) +	  if (info->remote_float || (!info->lsa->remote_list))  	    return true;  	  if (addrlist_match_proto (&from_addr->dest, info->lsa->remote_list, info->proto))  	    return true; @@ -892,13 +895,14 @@ link_socket_set_outgoing_addr (const struct buffer *buf,      {        struct link_socket_addr *lsa = info->lsa;        if ( -	  /* new or changed address? */ -	  (!info->connection_established -	   || !addr_match_proto (&act->dest, &lsa->actual.dest, info->proto)) -	  /* address undef or address == remote or --float */ -	  && (info->remote_float -	      || !lsa->remote_list) -	      || addrlist_match_proto (&act->dest, lsa->remote_list, info->proto) +	  ( +	   /* new or changed address? */ +	   (!info->connection_established +	    || !addr_match_proto (&act->dest, &lsa->actual.dest, info->proto)) +	   /* address undef or address == remote or --float */ +	   && (info->remote_float +	       || !lsa->remote_list)) +	  || addrlist_match_proto (&act->dest, lsa->remote_list, info->proto)  	  )  	{  	  link_socket_connection_initiated (buf, info, act, common_name, es); diff --git a/openvpn/src/openvpn/ssl.c b/openvpn/src/openvpn/ssl.c index 60f5f67f..58ba2384 100644 --- a/openvpn/src/openvpn/ssl.c +++ b/openvpn/src/openvpn/ssl.c @@ -64,7 +64,6 @@  #include "ssl.h"  #include "ssl_verify.h"  #include "ssl_backend.h" -#include "multi.h"  #include "memdbg.h" @@ -1837,7 +1836,7 @@ push_peer_info(struct buffer *buf, struct tls_session *session)  	    buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc));          } -      /* push env vars that begin with UV_ and IV_OPENVPN_GUI_VERSION*/ +      /* push env vars that begin with UV_ and IV_OPENVPN_GUI_VERSION */        for (e=es->list; e != NULL; e=e->next)  	{  	  if (e->string) diff --git a/openvpn/src/openvpn/ssl_openssl.c b/openvpn/src/openvpn/ssl_openssl.c index f64177a8..e3926914 100644 --- a/openvpn/src/openvpn/ssl_openssl.c +++ b/openvpn/src/openvpn/ssl_openssl.c @@ -743,7 +743,7 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,    X509_STORE *store = NULL;    X509_NAME *xn = NULL;    BIO *in = NULL; -  int i, added = 0; +  int i, added = 0, prev = 0;    ASSERT(NULL != ctx); @@ -770,6 +770,11 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,                if (info->crl)                    X509_STORE_add_crl (store, info->crl); +              if (tls_server && !info->x509) +                { +                  msg (M_SSLERR, "X509 name was missing in TLS mode"); +                } +                if (info->x509)                  {                    X509_STORE_add_cert (store, info->x509); @@ -799,6 +804,15 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,                        sk_X509_NAME_push (cert_names, xn);                      }                  } + +              if (tls_server) { +                int cnum = sk_X509_NAME_num (cert_names); +                if (cnum != (prev + 1)) { +                  msg (M_WARN, "Cannot load CA certificate file %s (entry %d did not validate)", np(ca_file), added); +                } +                prev = cnum; +              } +              }            sk_X509_INFO_pop_free (info_stack, X509_INFO_free);          } @@ -806,8 +820,15 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,        if (tls_server)          SSL_CTX_set_client_CA_list (ctx->ctx, cert_names); -      if (!added || (tls_server && sk_X509_NAME_num (cert_names) != added)) -        msg (M_SSLERR, "Cannot load CA certificate file %s", np(ca_file)); +      if (!added) +        msg (M_SSLERR, "Cannot load CA certificate file %s (no entries were read)", np(ca_file)); + +      if (tls_server) { +        int cnum = sk_X509_NAME_num (cert_names); +        if (cnum != added) +          msg (M_SSLERR, "Cannot load CA certificate file %s (only %d of %d entries were valid X509 names)", np(ca_file), cnum, added); +      } +        if (in)          BIO_free (in);      } diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c index bd62b392..c1dcc5e2 100644 --- a/openvpn/src/openvpn/tun.c +++ b/openvpn/src/openvpn/tun.c @@ -466,7 +466,7 @@ init_tun (const char *dev,       /* --dev option */         */        if (strict_warn)  	{ -          struct addrinfo *curele; +	  struct addrinfo *curele;  	  ifconfig_sanity_check (tt->type == DEV_TYPE_TUN, tt->remote_netmask, tt->topology);  	  /* @@ -483,14 +483,14 @@ init_tun (const char *dev,       /* --dev option */  			    tt->remote_netmask);            } -          for(curele=remote_public;curele;curele=curele->ai_next) { -            if(curele->ai_family == AF_INET) -              check_addr_clash ("remote", -                                tt->type, -                                ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr, -			        tt->local, -			        tt->remote_netmask); -          } +	  for (curele=remote_public;curele;curele=curele->ai_next) { +	    if (curele->ai_family == AF_INET) +	      check_addr_clash ("remote", +				tt->type, +				((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr, +				tt->local, +				tt->remote_netmask); +         }  	  if (tt->type == DEV_TYPE_TAP || (tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET))  	    check_subnet_conflict (tt->local, tt->remote_netmask, "TUN/TAP adapter"); @@ -1501,19 +1501,38 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu    struct gc_arena gc = gc_new ();    bool opentun; +  int oldtunfd = tt->fd; +    for (i = 0; i < tt->options.dns_len; ++i) {      management_android_control (management, "DNSSERVER", -                                print_in_addr_t(tt->options.dns[i], 0, &gc)); +				print_in_addr_t(tt->options.dns[i], 0, &gc));    }    if(tt->options.domain)      management_android_control (management, "DNSDOMAIN", tt->options.domain); -  opentun = management_android_control (management, "OPENTUN", dev); +  int android_method = managment_android_persisttun_action (management); + +  /* Android 4.4 workaround */ +  if (oldtunfd >=0 && android_method == ANDROID_OPEN_AFTER_CLOSE) +    { +      close(oldtunfd); +      openvpn_sleep(2); +    } -  /* Pick up the fd from management interface after calling the OPENTUN command */ -  tt->fd = management->connection.lastfdreceived; -  management->connection.lastfdreceived=-1; +  if (oldtunfd >=0  && android_method == ANDROID_KEEP_OLD_TUN) { +    /* keep the old fd */ +    opentun = true; +  } else { +    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; +  } + +  if (oldtunfd>=0 && android_method == ANDROID_OPEN_BEFORE_CLOSE) +    close(oldtunfd);    /* Set the actual name to a dummy name */    tt->actual_name = string_alloc (ANDROID_TUNNAME, NULL); @@ -3148,9 +3167,9 @@ get_panel_reg (struct gc_arena *gc)        char enum_name[256];        char connection_string[256];        HKEY connection_key; -      char name_data[256]; +      WCHAR name_data[256];        DWORD name_type; -      const char name_string[] = "Name"; +      const WCHAR name_string[] = L"Name";        len = sizeof (enum_name);        status = RegEnumKeyEx( @@ -3184,12 +3203,12 @@ get_panel_reg (struct gc_arena *gc)        else  	{  	  len = sizeof (name_data); -	  status = RegQueryValueEx( +	  status = RegQueryValueExW(  				   connection_key,  				   name_string,  				   NULL,  				   &name_type, -				   name_data, +				   (LPBYTE) name_data,  				   &len);  	  if (status != ERROR_SUCCESS || name_type != REG_SZ) @@ -3197,10 +3216,15 @@ get_panel_reg (struct gc_arena *gc)  		 NETWORK_CONNECTIONS_KEY, connection_string, name_string);  	  else  	    { +              int n; +              LPSTR name;  	      struct panel_reg *reg;  	      ALLOC_OBJ_CLEAR_GC (reg, struct panel_reg, gc); -	      reg->name = string_alloc (name_data, gc); +              n = WideCharToMultiByte (CP_UTF8, 0, name_data, -1, NULL, 0, NULL, NULL); +              name = gc_malloc (n, false, gc); +              WideCharToMultiByte (CP_UTF8, 0, name_data, -1, name, n, NULL, NULL); +              reg->name = name;  	      reg->guid = string_alloc (enum_name, gc);  	      /* link into return list */ @@ -3410,7 +3434,7 @@ static void  at_least_one_tap_win (const struct tap_reg *tap_reg)  {    if (!tap_reg) -    msg (M_FATAL, "There are no TAP-Windows adapters on this system.  You should be able to create a TAP-Windows adapter by going to Start -> All Programs -> " PACKAGE_NAME " -> Add a new TAP-Windows virtual ethernet adapter."); +    msg (M_FATAL, "There are no TAP-Windows adapters on this system.  You should be able to create a TAP-Windows adapter by going to Start -> All Programs -> TAP-Windows -> Utilities -> Add a new TAP-Windows virtual ethernet adapter.");  }  /* | 
