diff options
Diffstat (limited to 'openvpn/src')
| -rw-r--r-- | openvpn/src/openvpn/error.c | 11 | ||||
| -rw-r--r-- | openvpn/src/openvpn/error.h | 2 | ||||
| -rw-r--r-- | openvpn/src/openvpn/init.c | 7 | ||||
| -rw-r--r-- | openvpn/src/openvpn/manage.c | 4 | ||||
| -rw-r--r-- | openvpn/src/openvpn/options.c | 25 | ||||
| -rw-r--r-- | openvpn/src/openvpn/plugin.c | 62 | ||||
| -rw-r--r-- | openvpn/src/openvpn/route.c | 45 | ||||
| -rw-r--r-- | openvpn/src/openvpn/socket.c | 548 | ||||
| -rw-r--r-- | openvpn/src/openvpn/socket.h | 19 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl_common.h | 1 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl_verify_openssl.h | 2 | ||||
| -rw-r--r-- | openvpn/src/openvpn/tun.c | 22 | ||||
| -rw-r--r-- | openvpn/src/openvpn/tun.h | 4 | 
13 files changed, 288 insertions, 464 deletions
| diff --git a/openvpn/src/openvpn/error.c b/openvpn/src/openvpn/error.c index 8396fe01..6848425e 100644 --- a/openvpn/src/openvpn/error.c +++ b/openvpn/src/openvpn/error.c @@ -201,8 +201,15 @@ int x_msg_line_num; /* GLOBAL */  void x_msg (const unsigned int flags, const char *format, ...)  { -  struct gc_arena gc;    va_list arglist; +  va_start (arglist, format); +  x_msg_va (flags, format, arglist); +  va_end (arglist); +} + +void x_msg_va (const unsigned int flags, const char *format, va_list arglist) +{ +  struct gc_arena gc;  #if SYSLOG_CAPABILITY    int level;  #endif @@ -237,9 +244,7 @@ void x_msg (const unsigned int flags, const char *format, ...)    m1 = (char *) gc_malloc (ERR_BUF_SIZE, false, &gc);    m2 = (char *) gc_malloc (ERR_BUF_SIZE, false, &gc); -  va_start (arglist, format);    vsnprintf (m1, ERR_BUF_SIZE, format, arglist); -  va_end (arglist);    m1[ERR_BUF_SIZE - 1] = 0; /* windows vsnprintf needs this */    if ((flags & M_ERRNO) && e) diff --git a/openvpn/src/openvpn/error.h b/openvpn/src/openvpn/error.h index aedb7c37..27c48b69 100644 --- a/openvpn/src/openvpn/error.h +++ b/openvpn/src/openvpn/error.h @@ -182,6 +182,8 @@ void x_msg (const unsigned int flags, const char *format, ...)  #endif      ; /* should be called via msg above */ +void x_msg_va (const unsigned int flags, const char *format, va_list arglist); +  /*   * Function prototypes   */ diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c index b2013923..cd5ebd3d 100644 --- a/openvpn/src/openvpn/init.c +++ b/openvpn/src/openvpn/init.c @@ -2488,6 +2488,13 @@ 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"); +    if (script_method == SM_SYSTEM)      msg (M_WARN, "NOTE: --script-security method='system' is deprecated due to the fact that passed parameters will be subject to shell expansion");  } diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c index 77d40833..45e0bd43 100644 --- a/openvpn/src/openvpn/manage.c +++ b/openvpn/src/openvpn/manage.c @@ -1567,7 +1567,7 @@ man_listen (struct management *man)        else  #endif  	{ -	  man->connection.sd_top = create_socket_tcp (); +	  man->connection.sd_top = create_socket_tcp (AF_INET);  	  socket_bind (man->connection.sd_top, &man->settings.local, "MANAGEMENT");  	} @@ -1633,7 +1633,7 @@ man_connect (struct management *man)    else  #endif      { -      man->connection.sd_cli = create_socket_tcp (); +      man->connection.sd_cli = create_socket_tcp (AF_INET);        status = openvpn_connect (man->connection.sd_cli,  				&man->settings.local,  				5, diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c index a3029fc2..528583fe 100644 --- a/openvpn/src/openvpn/options.c +++ b/openvpn/src/openvpn/options.c @@ -62,6 +62,10 @@  #include "memdbg.h" +#ifdef MANAGMENT_EXTERNAL_KEY +#define EXTERNAL_KEY_STRING "EXTERNAL_PRIVATE_KEY" +#endif +  const char title_string[] =    PACKAGE_STRING    " " TARGET_ALIAS @@ -106,8 +110,7 @@ const char title_string[] =  #if ENABLE_IP_PKTINFO    " [MH]"  #endif -  " [PF_INET6]" -  " [IPv6 payload 20110522-1 (2.2.0)]" +  " [IPv6]"    " built on " __DATE__  ; @@ -2183,6 +2186,11 @@ options_postprocess_verify_ce (const struct options *options, const struct conne        else  #endif  #ifdef ENABLE_CRYPTOAPI +#ifdef MANAGMENT_EXTERNAL_KEY +    if((options->management_flags & MF_EXTERNAL_KEY) && !strcmp(options->priv_key_file,EXTERNAL_KEY_STRING)==0) +		msg (M_USAGE, "--key and --management-external-key are mutually exclusive"); +#endif +        if (options->cryptoapi_cert)  	{  	  if ((!(options->ca_file)) && (!(options->ca_path))) @@ -2357,14 +2365,6 @@ options_postprocess_mutate_ce (struct options *o, struct connection_entry *ce)  #endif            } -#ifdef MANAGMENT_EXTERNAL_KEY -  if(o->management_flags & MF_EXTERNAL_KEY) { -	  if(o->priv_key_file) -		  msg (M_USAGE, "--key and --management-external-key are mutually exclusive"); -	  /* set a filename for nicer output in the logs */ -	  o->priv_key_file = "EXTERNAL_PRIVATE_KEY"; -  } -#endif    /*     * Set MTU defaults     */ @@ -2640,7 +2640,7 @@ options_postprocess_filechecks (struct options *options)  #ifdef MANAGMENT_EXTERNAL_KEY    if(!options->management_flags & MF_EXTERNAL_KEY)  #endif -  errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->priv_key_file, R_OK, +     errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->priv_key_file, R_OK,                               "--key");    errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->pkcs12_file, R_OK,                               "--pkcs12"); @@ -4154,6 +4154,9 @@ add_option (struct options *options,      {        VERIFY_PERMISSION (OPT_P_GENERAL);        options->management_flags |= MF_EXTERNAL_KEY; +	  /* Set priv key file name only if not defined, so --key and this option can be checked later */ +	  if(!options->priv_key_file) +		  options->priv_key_file = EXTERNAL_KEY_STRING;      }  #endif  #ifdef MANAGEMENT_DEF_AUTH diff --git a/openvpn/src/openvpn/plugin.c b/openvpn/src/openvpn/plugin.c index 7ce2f5e7..d785daec 100644 --- a/openvpn/src/openvpn/plugin.c +++ b/openvpn/src/openvpn/plugin.c @@ -287,6 +287,65 @@ plugin_init_item (struct plugin *p, const struct plugin_option *o)  }  static void +plugin_vlog (openvpn_plugin_log_flags_t flags, const char *name, const char *format, va_list arglist) +{ +  unsigned int msg_flags; + +  if (!format) +    return; + +  if (!name || name[0] == '\0') +    { +      msg (D_PLUGIN_DEBUG, "PLUGIN: suppressed log message from plugin with unknown name"); +      return; +    } + +  if (flags & PLOG_ERR) +    msg_flags = M_INFO | M_NONFATAL; +  else if (flags & PLOG_WARN) +    msg_flags = M_INFO | M_WARN; +  else if (flags & PLOG_NOTE) +    msg_flags = M_INFO; +  else if (flags & PLOG_DEBUG) +    msg_flags = D_PLUGIN_DEBUG; + +  if (flags & PLOG_ERRNO) +    msg_flags |= M_ERRNO; +  if (flags & PLOG_NOMUTE) +    msg_flags |= M_NOMUTE; + +  if (MSG_TEST (msg_flags)) +    { +      struct gc_arena gc; +      char* msg_fmt; + +      /* Never add instance prefix; not thread safe */ +      msg_flags |= M_NOIPREFIX; + +      gc_init (&gc); +      msg_fmt = gc_malloc (ERR_BUF_SIZE, false, &gc); +      openvpn_snprintf (msg_fmt, ERR_BUF_SIZE, "PLUGIN %s: %s", name, format); +      x_msg_va (msg_flags, msg_fmt, arglist); + +      gc_free (&gc); +    } +} + +static void +plugin_log (openvpn_plugin_log_flags_t flags, const char *name, const char *format, ...) +{ +  va_list arglist; +  va_start (arglist, format); +  plugin_vlog (flags, name, format, arglist); +  va_end (arglist); +} + +static struct openvpn_plugin_callbacks callbacks = { +  plugin_log, +  plugin_vlog +}; + +static void  plugin_open_item (struct plugin *p,  		  const struct plugin_option *o,  		  struct openvpn_plugin_string_list **retlist, @@ -312,7 +371,8 @@ plugin_open_item (struct plugin *p,        if (p->open3) {          struct openvpn_plugin_args_open_in args = { p->plugin_type_mask,                                                      (const char ** const) o->argv, -                                                    (const char ** const) envp }; +                                                    (const char ** const) envp, +                                                    &callbacks };          struct openvpn_plugin_args_open_return retargs;          CLEAR(retargs); diff --git a/openvpn/src/openvpn/route.c b/openvpn/src/openvpn/route.c index e908be99..caa2459b 100644 --- a/openvpn/src/openvpn/route.c +++ b/openvpn/src/openvpn/route.c @@ -268,12 +268,14 @@ is_special_addr (const char *addr_str)  static bool  init_route (struct route *r, -	    struct resolve_list *network_list, +	    struct addrinfo **network_list,  	    const struct route_option *ro,  	    const struct route_list *rl)  {    const in_addr_t default_netmask = IPV4_NETMASK_HOST;    bool status; +  int ret; +  struct in_addr special;    CLEAR (*r);    r->option = ro; @@ -284,19 +286,22 @@ init_route (struct route *r,      {        goto fail;      } -   -  if (!get_special_addr (rl, ro->network, &r->network, &status)) + + +  /* get_special_addr replaces specialaddr with a special ip addr +     like gw. getaddrinfo is called to convert a a addrinfo struct */ + +  if(get_special_addr (rl, ro->network, &special.s_addr, &status))      { -      r->network = getaddr_multi ( -				  GETADDR_RESOLVE -				  | GETADDR_HOST_ORDER -				  | GETADDR_WARN_ON_SIGNAL, -				  ro->network, -				  0, -				  &status, -				  NULL, -				  network_list); +      special.s_addr = htonl(special.s_addr); +      ret = openvpn_getaddrinfo(0, inet_ntoa(special), 0, NULL, +                                AF_INET, network_list);      } +  else +    ret = openvpn_getaddrinfo(GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL, +                              ro->network, 0, NULL, AF_INET, network_list); + +  status = (ret == 0);    if (!status)      goto fail; @@ -642,11 +647,8 @@ init_route_list (struct route_list *rl,      bool warned = false;      for (i = 0; i < opt->n; ++i)        { -	struct resolve_list netlist; +        struct addrinfo* netlist;  	struct route r; -	int k; - -        CLEAR(netlist);		/* init_route() will not always init this */  	if (!init_route (&r,  			 &netlist, @@ -655,16 +657,12 @@ init_route_list (struct route_list *rl,  	  ret = false;  	else  	  { -	    if (!netlist.len) -	      { -		netlist.data[0] = r.network; -		netlist.len = 1; -	      } -	    for (k = 0; k < netlist.len; ++k) +            struct addrinfo* curele; +            for (curele	= netlist; curele; curele = curele->ai_next)  	      {  		if (j < rl->capacity)  		  { -		    r.network = netlist.data[k]; +                    r.network = ntohl(((struct sockaddr_in*)(curele)->ai_addr)->sin_addr.s_addr);  		    rl->routes[j++] = r;  		  }  		else @@ -676,6 +674,7 @@ init_route_list (struct route_list *rl,  		      }  		  }  	      } +            freeaddrinfo(netlist);  	  }        }      rl->n = j; diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c index 339470b0..bb973bc9 100644 --- a/openvpn/src/openvpn/socket.c +++ b/openvpn/src/openvpn/socket.c @@ -94,220 +94,53 @@ h_errno_msg(int h_errno_err)   */  in_addr_t  getaddr (unsigned int flags, -	 const char *hostname, -	 int resolve_retry_seconds, -	 bool *succeeded, -	 volatile int *signal_received) +         const char *hostname, +         int resolve_retry_seconds, +         bool *succeeded, +         volatile int *signal_received)  { -  return getaddr_multi (flags, hostname, resolve_retry_seconds, succeeded, signal_received, NULL); -} - -in_addr_t -getaddr_multi (unsigned int flags, -	 const char *hostname, -	 int resolve_retry_seconds, -	 bool *succeeded, -	 volatile int *signal_received, -	 struct resolve_list *reslist) -{ -  struct in_addr ia; +  struct addrinfo *ai;    int status; -  int sigrec = 0; -  int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS; -  struct gc_arena gc = gc_new (); - -  if (reslist) -    reslist->len = 0; - -  if (flags & GETADDR_RANDOMIZE) -    hostname = hostname_randomize(hostname, &gc); - -  if (flags & GETADDR_MSG_VIRT_OUT) -    msglevel |= M_MSG_VIRT_OUT; - -  CLEAR (ia); -  if (succeeded) -    *succeeded = false; - -  if ((flags & (GETADDR_FATAL_ON_SIGNAL|GETADDR_WARN_ON_SIGNAL)) -      && !signal_received) -    signal_received = &sigrec; - -  status = openvpn_inet_aton (hostname, &ia); /* parse ascii IP address */ - -  if (status != OIA_IP) /* parse as IP address failed? */ -    { -      const int fail_wait_interval = 5; /* seconds */ -      int resolve_retries = (flags & GETADDR_TRY_ONCE) ? 1 : (resolve_retry_seconds / fail_wait_interval); -      struct hostent *h; -      const char *fmt; -      int level = 0; - -      CLEAR (ia); - -      fmt = "RESOLVE: Cannot resolve host address: %s: %s"; -      if ((flags & GETADDR_MENTION_RESOLVE_RETRY) -	  && !resolve_retry_seconds) -	fmt = "RESOLVE: Cannot resolve host address: %s: %s (I would have retried this name query if you had specified the --resolv-retry option.)"; - -      if (!(flags & GETADDR_RESOLVE) || status == OIA_ERROR) -	{ -	  msg (msglevel, "RESOLVE: Cannot parse IP address: %s", hostname); -	  goto done; -	} - -#ifdef ENABLE_MANAGEMENT -      if (flags & GETADDR_UPDATE_MANAGEMENT_STATE) -	{ -	  if (management) -	    management_set_state (management, -				  OPENVPN_STATE_RESOLVE, -				  NULL, -				  (in_addr_t)0, -				  (in_addr_t)0); -	} -#endif - -      /* -       * Resolve hostname -       */ -      while (true) -	{ -	  /* try hostname lookup */ -#if defined(HAVE_RES_INIT) -	  res_init (); -#endif -	  h = gethostbyname (hostname); - -	  if (signal_received) -	    { -	      get_signal (signal_received); -	      if (*signal_received) /* were we interrupted by a signal? */ -		{ -		  h = NULL; -		  if (*signal_received == SIGUSR1) /* ignore SIGUSR1 */ -		    { -		      msg (level, "RESOLVE: Ignored SIGUSR1 signal received during DNS resolution attempt"); -		      *signal_received = 0; -		    } -		  else -		    goto done; -		} -	    } - -	  /* success? */ -	  if (h) -	    break; - -	  /* resolve lookup failed, should we -	     continue or fail? */ - -	  level = msglevel; -	  if (resolve_retries > 0) -	    level = D_RESOLVE_ERRORS; - -	  msg (level, -	       fmt, -	       hostname, -	       h_errno_msg (h_errno)); - -	  if (--resolve_retries <= 0) -	    goto done; - -	  openvpn_sleep (fail_wait_interval); -	} - -      if (h->h_addrtype != AF_INET || h->h_length != 4) -	{ -	    msg (msglevel, "RESOLVE: Sorry, but we only accept IPv4 DNS names: %s", hostname); -	    goto done; -	} - -      ia.s_addr = *(in_addr_t *) (h->h_addr_list[0]); - -      if (ia.s_addr) -	{ -	  if (h->h_addr_list[1]) /* more than one address returned */ -	    { -	      int n = 0; - -	      /* count address list */ -	      while (h->h_addr_list[n]) -		++n; -	      ASSERT (n >= 2); - -	      msg (D_RESOLVE_ERRORS, "RESOLVE: NOTE: %s resolves to %d addresses", -		   hostname, -		   n); - -	      /* choose address randomly, for basic load-balancing capability */ -	      /*ia.s_addr = *(in_addr_t *) (h->h_addr_list[get_random () % n]);*/ - -	      /* choose first address */ -	      ia.s_addr = *(in_addr_t *) (h->h_addr_list[0]); - -	      if (reslist) -		{ -		  int i; -		  for (i = 0; i < n && i < SIZE(reslist->data); ++i) -		    { -		      in_addr_t a = *(in_addr_t *) (h->h_addr_list[i]); -		      if (flags & GETADDR_HOST_ORDER) -			a = ntohl(a); -		      reslist->data[i] = a; -		    } -		  reslist->len = i; -		} -	    } -	} - -      /* hostname resolve succeeded */ -      if (succeeded) -	*succeeded = true; -    } -  else -    { -      /* IP address parse succeeded */ -      if (succeeded) -	*succeeded = true; -    } - - done: -  if (signal_received && *signal_received) -    { -      int level = 0; -      if (flags & GETADDR_FATAL_ON_SIGNAL) -	level = M_FATAL; -      else if (flags & GETADDR_WARN_ON_SIGNAL) -	level = M_WARN; -      msg (level, "RESOLVE: signal received during DNS resolution attempt"); -    } - -  gc_free (&gc); -  return (flags & GETADDR_HOST_ORDER) ? ntohl (ia.s_addr) : ia.s_addr; +  status = openvpn_getaddrinfo(flags, hostname, resolve_retry_seconds, +							   signal_received, AF_INET, &ai); +  if(status==0) { +    struct in_addr ia; +    if(succeeded) +      *succeeded=true; +    ia = ((struct sockaddr_in*)ai->ai_addr)->sin_addr; +    freeaddrinfo(ai); +    return (flags & GETADDR_HOST_ORDER) ? ntohl (ia.s_addr) : ia.s_addr; +  } else { +    if(succeeded) +      *succeeded =false; +    return 0; +  }  } +  /* - * Translate IPv6 addr or hostname into struct addrinfo - * If resolve error, try again for - * resolve_retry_seconds seconds. + * Translate IPv4/IPv6 addr or hostname into struct addrinfo + * If resolve error, try again for resolve_retry_seconds seconds.   */ -bool -getaddr6 (unsigned int flags, -	 const char *hostname, -	 int resolve_retry_seconds, -	 volatile int *signal_received, -         int *gai_err, -	 struct sockaddr_in6 *in6) -{ -  bool success; -  struct addrinfo hints, *ai; +int +openvpn_getaddrinfo (unsigned int flags, +                     const char *hostname, +                     int resolve_retry_seconds, +                     volatile int *signal_received, +                     int ai_family, +                     struct addrinfo **res) +{ +  struct addrinfo hints;    int status;    int sigrec = 0;    int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS;    struct gc_arena gc = gc_new (); -  ASSERT(in6); +  ASSERT(res); + +#if defined(HAVE_RES_INIT) +  res_init (); +#endif    if (!hostname)      hostname = "::"; @@ -318,151 +151,111 @@ getaddr6 (unsigned int flags,    if (flags & GETADDR_MSG_VIRT_OUT)      msglevel |= M_MSG_VIRT_OUT; -  CLEAR (ai); -  success = false; -    if ((flags & (GETADDR_FATAL_ON_SIGNAL|GETADDR_WARN_ON_SIGNAL))        && !signal_received)      signal_received = &sigrec;    /* try numeric ipv6 addr first */    CLEAR(hints); -  hints.ai_family = AF_INET6; +  hints.ai_family = ai_family;    hints.ai_flags = AI_NUMERICHOST; -  if ((status = getaddrinfo(hostname, NULL, &hints, &ai))==0) -    { -      *in6 = *((struct sockaddr_in6 *)(ai->ai_addr)); -      freeaddrinfo(ai); -      ai = NULL; -    } -  if (gai_err) -    *gai_err = status; +  hints.ai_socktype = dnsflags_to_socktype(flags); +  status = getaddrinfo(hostname, NULL, &hints, res); -  if (status != 0) /* parse as IPv6 address failed? */ +  if (status != 0) /* parse as numeric address failed? */      {        const int fail_wait_interval = 5; /* seconds */        int resolve_retries = (flags & GETADDR_TRY_ONCE) ? 1 : (resolve_retry_seconds / fail_wait_interval);        const char *fmt;        int level = 0; -      int err; - -      ai = NULL;        fmt = "RESOLVE: Cannot resolve host address: %s: %s";        if ((flags & GETADDR_MENTION_RESOLVE_RETRY) -	  && !resolve_retry_seconds) -	fmt = "RESOLVE: Cannot resolve host address: %s: %s (I would have retried this name query if you had specified the --resolv-retry option.)"; +          && !resolve_retry_seconds) +        fmt = "RESOLVE: Cannot resolve host address: %s: %s (I would have retried this name query if you had specified the --resolv-retry option.)";        if (!(flags & GETADDR_RESOLVE) || status == EAI_FAIL) -	{ -	  msg (msglevel, "RESOLVE: Cannot parse IPv6 address: %s", hostname); -	  goto done; -	} +        { +          msg (msglevel, "RESOLVE: Cannot parse IP address: %s", hostname); +          goto done; +        }  #ifdef ENABLE_MANAGEMENT        if (flags & GETADDR_UPDATE_MANAGEMENT_STATE) -	{ -	  if (management) -	    management_set_state (management, -				  OPENVPN_STATE_RESOLVE, -				  NULL, -				  (in_addr_t)0, -				  (in_addr_t)0); -	} +        { +          if (management) +            management_set_state (management, +                                  OPENVPN_STATE_RESOLVE, +                                  NULL, +                                  (in_addr_t)0, +                                  (in_addr_t)0); +        }  #endif        /*         * Resolve hostname         */        while (true) -	{ -	  /* try hostname lookup */ +        { +          /* try hostname lookup */            hints.ai_flags = 0; -          hints.ai_socktype = dnsflags_to_socktype(flags); -	  dmsg (D_SOCKET_DEBUG, "GETADDR6 flags=0x%04x ai_family=%d ai_socktype=%d", -		flags, hints.ai_family, hints.ai_socktype); -          err = getaddrinfo(hostname, NULL, &hints, &ai); +          dmsg (D_SOCKET_DEBUG, "GETADDRINFO flags=0x%04x ai_family=%d ai_socktype=%d", +                flags, hints.ai_family, hints.ai_socktype); +          status = getaddrinfo(hostname, NULL, &hints, res); -          if (gai_err) -            *gai_err = err; - -	  if (signal_received) -	    { -	      get_signal (signal_received); -	      if (*signal_received) /* were we interrupted by a signal? */ -		{ -                  if (0 == err) { -                    ASSERT(ai); -                    freeaddrinfo(ai); -                    ai = NULL; +          if (signal_received) +            { +              get_signal (signal_received); +              if (*signal_received) /* were we interrupted by a signal? */ +                { +                  if (0 == status) { +                    ASSERT(res); +                    freeaddrinfo(*res); +                    res = NULL;                    } -		  if (*signal_received == SIGUSR1) /* ignore SIGUSR1 */ -		    { -		      msg (level, "RESOLVE: Ignored SIGUSR1 signal received during DNS resolution attempt"); -		      *signal_received = 0; -		    } -		  else -		    goto done; -		} -	    } - -	  /* success? */ -	  if (0 == err) -	    break; - -	  /* resolve lookup failed, should we -	     continue or fail? */ - -	  level = msglevel; -	  if (resolve_retries > 0) -	    level = D_RESOLVE_ERRORS; - -	  msg (level, -	       fmt, -	       hostname, -	       gai_strerror(err)); - -	  if (--resolve_retries <= 0) -	    goto done; - -	  openvpn_sleep (fail_wait_interval); -	} +                  if (*signal_received == SIGUSR1) /* ignore SIGUSR1 */ +                    { +                      msg (level, "RESOLVE: Ignored SIGUSR1 signal received during DNS resolution attempt"); +                      *signal_received = 0; +                    } +                  else +                    goto done; +                } +            } -      ASSERT(ai); +          /* success? */ +          if (0 == status) +            break; -      if (!ai->ai_next) -        *in6 = *((struct sockaddr_in6*)(ai->ai_addr)); -      else  -        /* more than one address returned */ -        { -          struct addrinfo *ai_cursor; -          int n = 0; -          /* count address list */ -          for (ai_cursor = ai; ai_cursor; ai_cursor = ai_cursor->ai_next) n++; -          ASSERT (n >= 2); +          /* resolve lookup failed, should we +             continue or fail? */ +          level = msglevel; +          if (resolve_retries > 0) +            level = D_RESOLVE_ERRORS; -          msg (D_RESOLVE_ERRORS, "RESOLVE: NOTE: %s resolves to %d ipv6 addresses, choosing one by random", +          msg (level, +               fmt,                 hostname, -               n); +               gai_strerror(status)); + +          if (--resolve_retries <= 0) +            goto done; -          /* choose address randomly, for basic load-balancing capability */ -	  n--; -          n %= get_random(); -          for (ai_cursor = ai; n; ai_cursor = ai_cursor->ai_next) n--; -          *in6 = *((struct sockaddr_in6*)(ai_cursor->ai_addr)); +          openvpn_sleep (fail_wait_interval);          } -      freeaddrinfo(ai); -      ai = NULL; +      ASSERT(res);        /* hostname resolve succeeded */ -      success = true; + +      /* Do not chose an IP Addresse by random or change the order * +       * of IP addresses, doing so will break RFC 3484 address selection * +       */      }    else      {        /* IP address parse succeeded */ -      success = true;      }   done: @@ -470,14 +263,14 @@ getaddr6 (unsigned int flags,      {        int level = 0;        if (flags & GETADDR_FATAL_ON_SIGNAL) -	level = M_FATAL; +        level = M_FATAL;        else if (flags & GETADDR_WARN_ON_SIGNAL) -	level = M_WARN; +        level = M_WARN;        msg (level, "RESOLVE: signal received during DNS resolution attempt");      }    gc_free (&gc); -  return success; +  return status;  }  /* @@ -653,18 +446,16 @@ update_remote (const char* host,      case AF_INET6:        if (host && addr)          { -          struct sockaddr_in6 sin6; -          int success; -          CLEAR(sin6); -          success = getaddr6 ( -                                    sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sockflags), -                                    host, -                                    1, -                                    NULL, -                                    NULL, -                                    &sin6); -          if ( success ) +          int status; +          struct addrinfo* ai; + +		  status = openvpn_getaddrinfo(sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sockflags), host, 1, NULL, AF_INET6, &ai); + +          if ( status ==0 )              { +			  struct sockaddr_in6 sin6; +			  CLEAR(sin6); +			  sin6 = *((struct sockaddr_in6*)ai->ai_addr);                if (!IN6_ARE_ADDR_EQUAL(&sin6.sin6_addr, &addr->addr.in6.sin6_addr))                {                  int port = addr->addr.in6.sin6_port; @@ -672,6 +463,7 @@ update_remote (const char* host,                  addr->addr.in6 = sin6;                   addr->addr.in6.sin6_port = port;                } +			  freeaddrinfo(ai);              }          }        break; @@ -830,11 +622,11 @@ link_socket_update_buffer_sizes (struct link_socket *ls, int rcvbuf, int sndbuf)   */  socket_descriptor_t -create_socket_tcp (void) +create_socket_tcp (int af)  {    socket_descriptor_t sd; -  if ((sd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) +  if ((sd = socket (af, SOCK_STREAM, IPPROTO_TCP)) < 0)      msg (M_ERR, "Cannot create TCP socket");  #ifndef WIN32 /* using SO_REUSEADDR on Windows will cause bind to succeed on port conflicts! */ @@ -847,18 +639,6 @@ create_socket_tcp (void)    }  #endif -#if 0 -  /* set socket linger options */ -  { -    struct linger linger; -    linger.l_onoff = 1; -    linger.l_linger = 2; -    if (setsockopt (sd, SOL_SOCKET, SO_LINGER, -		    (void *) &linger, sizeof (linger)) < 0) -      msg (M_ERR, "TCP: Cannot setsockopt SO_LINGER on TCP socket"); -  } -#endif -    return sd;  } @@ -913,25 +693,6 @@ create_socket_udp6 (const unsigned int flags)    return sd;  } -static socket_descriptor_t -create_socket_tcp6 (void) -{ -  socket_descriptor_t sd; - -  if ((sd = socket (PF_INET6, SOCK_STREAM, IPPROTO_TCP)) < 0) -    msg (M_ERR, "Cannot create TCP6 socket"); - -  /* set SO_REUSEADDR on socket */ -  { -    int on = 1; -    if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, -		    (void *) &on, sizeof (on)) < 0) -      msg (M_ERR, "TCP: Cannot setsockopt SO_REUSEADDR on TCP6 socket"); -  } - -  return sd; -} -  static void  create_socket (struct link_socket *sock)  { @@ -943,18 +704,18 @@ create_socket (struct link_socket *sock)  #ifdef ENABLE_SOCKS        if (sock->socks_proxy) -	sock->ctrl_sd = create_socket_tcp (); +	sock->ctrl_sd = create_socket_tcp (AF_INET);  #endif      }    else if (sock->info.proto == PROTO_TCPv4_SERVER  	   || sock->info.proto == PROTO_TCPv4_CLIENT)      { -      sock->sd = create_socket_tcp (); +      sock->sd = create_socket_tcp (AF_INET);      }    else if (sock->info.proto == PROTO_TCPv6_SERVER  	   || sock->info.proto == PROTO_TCPv6_CLIENT)      { -      sock->sd = create_socket_tcp6 (); +      sock->sd = create_socket_tcp (AF_INET6);      }    else if (sock->info.proto == PROTO_UDPv6)      { @@ -1314,15 +1075,7 @@ socket_connect (socket_descriptor_t *sd,        if (*signal_received)  	goto done; -      switch(local->addr.sa.sa_family) -	{ -	case PF_INET6: -	  *sd = create_socket_tcp6 (); -	  break; -	case PF_INET: -	  *sd = create_socket_tcp (); -	  break; -	} +	*sd = create_socket_tcp (local->addr.sa.sa_family);        if (bind_local)          socket_bind (*sd, local, "TCP Client"); @@ -1404,25 +1157,27 @@ resolve_bind_local (struct link_socket *sock)  	  break;  	case AF_INET6:  	    { -	      int success; +	      int status;  	      int err;  	      CLEAR(sock->info.lsa->local.addr.in6);  	      if (sock->local_host)  		{ -		  success = getaddr6(GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | GETADDR_FATAL, -				     sock->local_host, -				     0, -				     NULL, -				     &err, -				     &sock->info.lsa->local.addr.in6); +		  struct addrinfo *ai; + +		  status = openvpn_getaddrinfo(GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | GETADDR_FATAL, +									   sock->local_host, 0, NULL, AF_INET6, &ai); +		  if(status ==0) { +			  sock->info.lsa->local.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr)); +			  freeaddrinfo(ai); +		  }  		}  	      else  		{  		  sock->info.lsa->local.addr.in6.sin6_family = AF_INET6;  		  sock->info.lsa->local.addr.in6.sin6_addr = in6addr_any; -		  success = true; +		  status = 0;  		} -	      if (!success) +	      if (!status == 0)  		{  		  msg (M_FATAL, "getaddr6() failed for local \"%s\": %s",  		       sock->local_host, @@ -1479,7 +1234,7 @@ resolve_remote (struct link_socket *sock,  	    {  	      unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags);  	      int retry = 0; -	      bool status = false; +	      int status = -1;  	      if (sock->connection_profiles_defined && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)  		{ @@ -1516,40 +1271,27 @@ resolve_remote (struct link_socket *sock,  		  ASSERT (0);  		} -              switch(af) -                { -                  case AF_INET: -                    sock->info.lsa->remote.addr.in4.sin_addr.s_addr = getaddr ( -                          flags, -                          sock->remote_host, -                          retry, -                          &status, -                          signal_received); -                    break; -                  case AF_INET6: -                    status = getaddr6 ( -                        flags, -                        sock->remote_host, -                        retry, -                        signal_received, -                        NULL, -                        &sock->info.lsa->remote.addr.in6); -                    break; -                } - -	      dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", -		   flags, -		   phase, -		   retry, -		   signal_received ? *signal_received : -1, -		   status); - +		  struct addrinfo* ai; +		  /* Temporary fix, this need to be changed for dual stack */ +		  status = openvpn_getaddrinfo(flags, sock->remote_host, retry, +											  signal_received, af, &ai); +		  if(status == 0) { +			  sock->info.lsa->remote.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr)); +			  freeaddrinfo(ai); + +			  dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", +					flags, +					phase, +					retry, +					signal_received ? *signal_received : -1, +					status); +		  }  	      if (signal_received)  		{  		  if (*signal_received)  		    goto done;  		} -	      if (!status) +	      if (status!=0)  		{  		  if (signal_received)  		    *signal_received = SIGUSR1; @@ -1927,7 +1669,7 @@ link_socket_init_phase2 (struct link_socket *sock,  	    if (proxy_retry)  	      {  		openvpn_close_socket (sock->sd); -		sock->sd = create_socket_tcp (); +		sock->sd = create_socket_tcp (AF_INET);  	      }  	  } while (proxy_retry);  	} diff --git a/openvpn/src/openvpn/socket.h b/openvpn/src/openvpn/socket.h index 47c6e8eb..44f1098b 100644 --- a/openvpn/src/openvpn/socket.h +++ b/openvpn/src/openvpn/socket.h @@ -425,7 +425,7 @@ bool ip_or_dns_addr_safe (const char *addr, const bool allow_fqdn);  bool mac_addr_safe (const char *mac_addr);  bool ipv6_addr_safe (const char *ipv6_text_addr); -socket_descriptor_t create_socket_tcp (void); +socket_descriptor_t create_socket_tcp (int af);  socket_descriptor_t socket_do_accept (socket_descriptor_t sd,  				      struct link_socket_actual *act, @@ -467,11 +467,6 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *   * DNS resolution   */ -struct resolve_list { -  int len; -  in_addr_t data[16]; -}; -  #define GETADDR_RESOLVE               (1<<0)  #define GETADDR_FATAL                 (1<<1)  #define GETADDR_HOST_ORDER            (1<<2) @@ -494,12 +489,12 @@ in_addr_t getaddr (unsigned int flags,  		   bool *succeeded,  		   volatile int *signal_received); -in_addr_t getaddr_multi (unsigned int flags, -			 const char *hostname, -			 int resolve_retry_seconds, -			 bool *succeeded, -			 volatile int *signal_received, -			 struct resolve_list *reslist); +int openvpn_getaddrinfo (unsigned int flags, +                         const char *hostname, +                         int resolve_retry_seconds, +                         volatile int *signal_received, +                         int ai_family, +                         struct addrinfo **res);  /*   * Transport protocol naming and other details. diff --git a/openvpn/src/openvpn/ssl_common.h b/openvpn/src/openvpn/ssl_common.h index f3f43be2..cb259a96 100644 --- a/openvpn/src/openvpn/ssl_common.h +++ b/openvpn/src/openvpn/ssl_common.h @@ -288,7 +288,6 @@ struct tls_options  # define SSLF_CLIENT_CERT_NOT_REQUIRED (1<<0)  # define SSLF_USERNAME_AS_COMMON_NAME  (1<<1)  # define SSLF_AUTH_USER_PASS_OPTIONAL  (1<<2) -# define SSLF_NO_NAME_REMAPPING        (1<<3)  # define SSLF_OPT_VERIFY               (1<<4)  # define SSLF_CRL_VERIFY_DIR           (1<<5)    unsigned int ssl_flags; diff --git a/openvpn/src/openvpn/ssl_verify_openssl.h b/openvpn/src/openvpn/ssl_verify_openssl.h index afd6110b..5a7e0a19 100644 --- a/openvpn/src/openvpn/ssl_verify_openssl.h +++ b/openvpn/src/openvpn/ssl_verify_openssl.h @@ -73,6 +73,4 @@ int verify_callback (int preverify_ok, X509_STORE_CTX * ctx);  /** @} name Function for authenticating a new connection from a remote OpenVPN peer */ -char *_openssl_get_subject (X509 *cert, char *buf, int size); -  #endif /* SSL_VERIFY_OPENSSL_H_ */ diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c index 81979476..cd61baf4 100644 --- a/openvpn/src/openvpn/tun.c +++ b/openvpn/src/openvpn/tun.c @@ -925,7 +925,7 @@ do_ifconfig (struct tuntap *tt,  #elif defined(TARGET_OPENBSD)        /* -       * On OpenBSD, tun interfaces are persistant if created with +       * On OpenBSD, tun interfaces are persistent if created with         * "ifconfig tunX create", and auto-destroyed if created by         * opening "/dev/tunX" (so we just use the /dev/tunX)         */ @@ -1270,7 +1270,7 @@ do_ifconfig (struct tuntap *tt,    gc_free (&gc);  } -void +static void  clear_tuntap (struct tuntap *tuntap)  {    CLEAR (*tuntap); @@ -1379,6 +1379,13 @@ open_tun_generic (const char *dev, const char *dev_type, const char *dev_node,        if (!dynamic_opened)  	{ +	  /* has named device existed before? if so, don't destroy at end */ +	  if ( if_nametoindex( dev ) > 0 ) +	    { +	      msg (M_INFO, "TUN/TAP device %s exists previously, keep at program end", dev ); +	      tt->persistent_if = true; +	    } +  	  if ((tt->fd = open (tunname, O_RDWR)) < 0)  	    msg (M_ERR, "Cannot open TUN/TAP dev %s", tunname);  	} @@ -2116,7 +2123,7 @@ close_tun (struct tuntap* tt)  {    /* only *TAP* devices need destroying, tun devices auto-self-destruct     */ -  if (tt && tt->type == DEV_TYPE_TUN ) +  if (tt && (tt->type == DEV_TYPE_TUN || tt->persistent_if ) )      {        close_tun_generic (tt);        free(tt); @@ -2251,7 +2258,7 @@ close_tun (struct tuntap *tt)  {    /* only tun devices need destroying, tap devices auto-self-destruct     */ -  if (tt && tt->type != DEV_TYPE_TUN ) +  if (tt && ( tt->type != DEV_TYPE_TUN || tt->persistent_if ) )      {        close_tun_generic (tt);        free(tt); @@ -2389,7 +2396,12 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu  void  close_tun (struct tuntap *tt)  { -  if (tt) +  if (tt && tt->persistent_if )		/* keep pre-existing if around */ +    { +      close_tun_generic (tt); +      free (tt); +    } +  else if (tt)				/* close and destroy */      {        struct gc_arena gc = gc_new ();        struct argv argv; diff --git a/openvpn/src/openvpn/tun.h b/openvpn/src/openvpn/tun.h index 0f4f0123..c31ac001 100644 --- a/openvpn/src/openvpn/tun.h +++ b/openvpn/src/openvpn/tun.h @@ -137,6 +137,8 @@ struct tuntap    bool ipv6; +  bool persistent_if;		/* if existed before, keep on program end */ +    struct tuntap_options options; /* options set on command line */    char *actual_name; /* actual name of TUN/TAP dev, usually including unit number */ @@ -201,7 +203,7 @@ tuntap_defined (const struct tuntap *tt)   * Function prototypes   */ -void clear_tuntap (struct tuntap *tuntap); +static void clear_tuntap (struct tuntap *tuntap);  void open_tun (const char *dev, const char *dev_type, const char *dev_node,  	       struct tuntap *tt); | 
