diff options
Diffstat (limited to 'openvpn')
| -rw-r--r-- | openvpn/src/openvpn/init.c | 16 | ||||
| -rw-r--r-- | openvpn/src/openvpn/openvpn.h | 3 | ||||
| -rw-r--r-- | openvpn/src/openvpn/options.h | 2 | ||||
| -rw-r--r-- | openvpn/src/openvpn/proxy.c | 2 | ||||
| -rw-r--r-- | openvpn/src/openvpn/proxy.h | 2 | ||||
| -rw-r--r-- | openvpn/src/openvpn/socket.c | 172 | ||||
| -rw-r--r-- | openvpn/src/openvpn/socket.h | 18 | 
7 files changed, 175 insertions, 40 deletions
| diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c index 0f76b2cc..c42c0f78 100644 --- a/openvpn/src/openvpn/init.c +++ b/openvpn/src/openvpn/init.c @@ -130,16 +130,25 @@ management_callback_proxy_cmd (void *arg, const char **p)  #ifndef ENABLE_HTTP_PROXY            msg (M_WARN, "HTTP proxy support is not available");  #else -          struct http_proxy_options *ho; -          if (ce->proto != PROTO_TCP && ce->proto != PROTO_TCP_CLIENT )            { +          struct http_proxy_options *ho, *oldho; +         if (ce->proto != PROTO_TCP && ce->proto != PROTO_TCP_CLIENT )            {                msg (M_WARN, "HTTP proxy support only works for TCP based connections");                return false;              } +	  oldho = ce->http_proxy_options;            ho = init_http_proxy_options_once (&ce->http_proxy_options, gc);            ho->server = string_alloc (p[2], gc);            ho->port = string_alloc (p[3], gc);            ho->retry = true;            ho->auth_retry = (p[4] && streq (p[4], "nct") ? PAR_NCT : PAR_ALL); + +	  /* Save the old preresolved addrinfo we are using the same proxy again */ +	  if (oldho && +	      oldho->preresolved_proxy && +	      streq(oldho->server, ho->server) && +	      streq(oldho->port, ho->port)) +	    ho->preresolved_proxy = oldho->preresolved_proxy; +            ret = true;  #endif          } @@ -2690,10 +2699,9 @@ do_init_socket_1 (struct context *c, const int mode)    link_socket_init_phase1 (c->c2.link_socket,  			   c->options.ce.local,  			   c->options.ce.local_port, -			   c->options.ce.preresolved_local,  			   c->options.ce.remote,  			   c->options.ce.remote_port, -			   c->options.ce.preresolved_remote, +			   c->c1.preresolved,  			   c->options.ce.proto,  			   c->options.ce.af,  			   c->options.ce.bind_ipv6_only, diff --git a/openvpn/src/openvpn/openvpn.h b/openvpn/src/openvpn/openvpn.h index 606a4f59..3ed7810a 100644 --- a/openvpn/src/openvpn/openvpn.h +++ b/openvpn/src/openvpn/openvpn.h @@ -166,6 +166,9 @@ struct context_1    /* tunnel session keys */    struct key_schedule ks; +  /* preresolved host names */ +  struct preresovled_host *preresolved; +    /* persist crypto sequence number to/from file */    struct packet_id_persist pid_persist; diff --git a/openvpn/src/openvpn/options.h b/openvpn/src/openvpn/options.h index ddeb8b38..dafb8ff6 100644 --- a/openvpn/src/openvpn/options.h +++ b/openvpn/src/openvpn/options.h @@ -93,8 +93,6 @@ struct connection_entry    const char *remote_port;    const char *local;    const char *remote; -  struct addrinfo *preresolved_remote; -  struct addrinfo *preresolved_local;    bool remote_float;    bool bind_defined;    bool bind_ipv6_only; diff --git a/openvpn/src/openvpn/proxy.c b/openvpn/src/openvpn/proxy.c index f7f06487..53cd1cda 100644 --- a/openvpn/src/openvpn/proxy.c +++ b/openvpn/src/openvpn/proxy.c @@ -478,6 +478,8 @@ http_proxy_new (const struct http_proxy_options *o)      msg (M_FATAL, "Sorry, this version of " PACKAGE_NAME " was built without NTLM Proxy support.");  #endif +  p->preresoveld_proxy = o->preresolved_proxy; +    p->defined = true;    return p;  } diff --git a/openvpn/src/openvpn/proxy.h b/openvpn/src/openvpn/proxy.h index 0e7a6dfb..cea910cf 100644 --- a/openvpn/src/openvpn/proxy.h +++ b/openvpn/src/openvpn/proxy.h @@ -59,6 +59,7 @@ struct http_proxy_options {    const char *auth_file;    const char *http_version;    const char *user_agent; +  struct addrinfo *preresolved_proxy;    struct http_custom_header custom_headers[MAX_CUSTOM_HTTP_HEADER];  }; @@ -73,6 +74,7 @@ struct http_proxy_info {    int auth_method;    struct http_proxy_options options;    struct user_pass up; +  struct addrinfo* preresoveld_proxy;    char *proxy_authenticate;    bool queried_creds;  }; diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c index 26ef14c3..f99669aa 100644 --- a/openvpn/src/openvpn/socket.c +++ b/openvpn/src/openvpn/socket.c @@ -118,20 +118,114 @@ getaddr (unsigned int flags,    }  } +static inline bool +streqnull (const char* a, const char* b) +{ +  if (a == NULL && b == NULL) +    return true; +  else if (a == NULL || b == NULL) +    return false; +  else +    return streq (a, b); +} + +static int +get_preresolved_host (struct preresovled_host* preresolved, +		      const char* hostname, +		      const char* servname, +		      int ai_family, +		      int resolve_flags, +		      struct addrinfo **ai) +{ +  struct preresovled_host *ph; +  int flags; + +  /* Only use flags that are relevant for the structure */ +  flags = resolve_flags & GETADDR_PRERESOLVE_MASK; + +  for (ph = preresolved; ph ; ph = ph->next) +    { +      if (streqnull (ph->hostname, hostname) && +	  streqnull (ph->servname, servname) && +	  ph->ai_family == ai_family && +	  ph->flags == flags) +	{ +	  *ai = ph->ai; +	  return 0; +	} +    } +  return -1; +} + + +static int +do_preresolve_host (struct context *c, +		    const char *hostname, +		    const char *servname, +		    const int af, +		    const int flags) +{ +  struct addrinfo *ai; +  if (get_preresolved_host(c->c1.preresolved, +			   hostname, +			     servname, +			     af, +			     flags, +			   &ai)) +    { +      int status; +      status = openvpn_getaddrinfo (flags, hostname, servname, +				    c->options.resolve_retry_seconds, NULL, +				    af, &ai); +      if (status == 0) +	{ +	  struct preresovled_host *ph; + +	  ALLOC_OBJ_CLEAR_GC (ph, struct preresovled_host, &c->gc); +	  ph->ai = ai; +	  ph->hostname = hostname; +	  ph->servname = servname; +	  ph->flags = flags & GETADDR_PRERESOLVE_MASK; + +	  if (!c->c1.preresolved) +	    c->c1.preresolved = ph; +	  else +	    { +	      struct preresovled_host *prev = c->c1.preresolved; +	      while (prev->next) +		prev = prev->next; +	      prev->next = ph; +	    } + +	  gc_addspecial (ai, &gc_freeaddrinfo_callback, &c->gc); + +	} +      return status; +    } +  else +    { +      /* already in preresolved list, return success */ +      return 0; +    } +}  void  do_preresolve(struct context *c)  {    int i;    struct connection_list *l = c->options.connection_list; +  const unsigned int preresolve_flags = GETADDR_RESOLVE| +    GETADDR_UPDATE_MANAGEMENT_STATE| +    GETADDR_MENTION_RESOLVE_RETRY| +    GETADDR_FATAL;    for (i = 0; i < l->len; ++i) {      int status;      const char *remote; +    int flags = preresolve_flags; +      struct connection_entry* ce = c->options.connection_list->array[i]; -    unsigned int flags = GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE| -      GETADDR_MENTION_RESOLVE_RETRY|GETADDR_FATAL;      if (proto_is_dgram(ce->proto))        flags |= GETADDR_DATAGRAM; @@ -144,28 +238,45 @@ do_preresolve(struct context *c)      else        remote = ce->remote; -    if (! ce->preresolved_remote) +    /* HTTP remote hostname does not need to be resolved */ +    if (! ce->http_proxy_options)        { -	status = openvpn_getaddrinfo (flags, remote, ce->remote_port, -				      c->options.resolve_retry_seconds, NULL, -				      ce->af, &ce->preresolved_remote); - -	if (status != 0) +	status = do_preresolve_host (c, remote, ce->remote_port, ce->af, flags); +	if (!status)  	  goto err; -	gc_addspecial (ce->preresolved_remote, &gc_freeaddrinfo_callback, &c->gc);        }      flags |= GETADDR_PASSIVE; -    if (ce->bind_local && !ce->preresolved_local) + +    if (ce->bind_local)        { -	status = openvpn_getaddrinfo (flags, ce->local, ce->local_port, -				      c->options.resolve_retry_seconds, NULL, -				      ce->af, &ce->preresolved_local); +	status = do_preresolve_host (c, ce->local, ce->local_port, ce->af, flags); +	if (status != 0) +	  goto err; + +      } +    /* Preresolve proxy */ +    if (ce->http_proxy_options) +      { +	status = do_preresolve_host(c, +				    ce->http_proxy_options->server, +				    ce->http_proxy_options->port, +				    ce->af, +				    preresolve_flags);  	if (status != 0)  	  goto err; -	gc_addspecial (ce->preresolved_local, &gc_freeaddrinfo_callback, &c->gc); +      } +    if (ce->socks_proxy_server) +      { +	status = do_preresolve_host (c, +				     ce->socks_proxy_server, +				     ce->socks_proxy_port, +				     ce->af, +				     flags); +	if (status != 0) +	  goto err;        }    } @@ -1211,12 +1322,14 @@ resolve_bind_local (struct link_socket *sock, const sa_family_t af)  	flags |= GETADDR_DATAGRAM;        /* will return AF_{INET|INET6}from local_host */ -      if (sock->preresolved_local) -	{ -	  status=0; -	  sock->info.lsa->bind_local=sock->preresolved_local; -	} -      else +      status = get_preresolved_host (sock->preresolved, +				     sock->local_host, +				     sock->local_port, +				     af, +				     flags, +				     &sock->info.lsa->bind_local); + +      if (status)  	status = openvpn_getaddrinfo(flags, sock->local_host, sock->local_port, 0,  				   NULL, af, &sock->info.lsa->bind_local); @@ -1302,12 +1415,13 @@ resolve_remote (struct link_socket *sock,  	      ASSERT (0);  	    } -	  if (sock->preresolved_remote) -	    { -	      status = 0; -	      ai = sock->preresolved_remote; -	    } -	  else + +	  status = get_preresolved_host (sock->preresolved, +					 sock->remote_host, +					 sock->remote_port, +					 sock->info.af, +					 flags, &ai); +	  if (status)  	    status = openvpn_getaddrinfo (flags, sock->remote_host, sock->remote_port,  					  retry, signal_received, sock->info.af, &ai); @@ -1412,10 +1526,9 @@ void  link_socket_init_phase1 (struct link_socket *sock,  			 const char *local_host,  			 const char *local_port, -			 struct addrinfo *local_preresolved,  			 const char *remote_host,  			 const char *remote_port, -			 struct addrinfo *remote_preresolved, +			 struct preresovled_host *preresolved,  			 int proto,  			 sa_family_t af,  			 bool bind_ipv6_only, @@ -1448,10 +1561,9 @@ link_socket_init_phase1 (struct link_socket *sock,    sock->local_host = local_host;    sock->local_port = local_port; -  sock->preresolved_local = local_preresolved;    sock->remote_host = remote_host;    sock->remote_port = remote_port; -  sock->preresolved_remote = remote_preresolved; +  sock->preresolved = preresolved;  #ifdef ENABLE_HTTP_PROXY    sock->http_proxy = http_proxy; diff --git a/openvpn/src/openvpn/socket.h b/openvpn/src/openvpn/socket.h index 8a118cd1..7c0b040c 100644 --- a/openvpn/src/openvpn/socket.h +++ b/openvpn/src/openvpn/socket.h @@ -77,6 +77,16 @@ struct openvpn_sockaddr    } addr;  }; +/* struct to hold preresolved host names */ +struct preresovled_host { +    const char *hostname; +    const char *servname; +    int ai_family; +    int flags; +    struct addrinfo *ai; +    struct preresovled_host *next; +}; +  /* actual address of remote, based on source address of received packets */  struct link_socket_actual  { @@ -186,10 +196,9 @@ struct link_socket    const char *remote_host;    const char *remote_port; -  struct addrinfo *preresolved_remote;    const char *local_host;    const char *local_port; -  struct addrinfo *preresolved_local; +  struct preresovled_host *preresolved;    bool bind_local;  # define INETD_NONE   0 @@ -308,10 +317,9 @@ void  link_socket_init_phase1 (struct link_socket *sock,  			 const char *local_host,  			 const char *local_port, -			 struct addrinfo *local_preresolved,  			 const char *remote_host,  			 const char *remote_port, -			 struct addrinfo *remote_preresolved, +			 struct preresovled_host *preresolved,  			 int proto,  			 sa_family_t af,  			 bool bind_ipv6_only, @@ -520,6 +528,8 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *  #define GETADDR_PASSIVE               (1<<10)  #define GETADDR_DATAGRAM              (1<<11) +#define GETADDR_PRERESOLVE_MASK		GETADDR_DATAGRAM|GETADDR_PASSIVE +  in_addr_t getaddr (unsigned int flags,  		   const char *hostname,  		   int resolve_retry_seconds, | 
