diff options
| author | Arne Schwabe <arne@rfc2549.org> | 2014-11-26 00:28:48 +0100 | 
|---|---|---|
| committer | Arne Schwabe <arne@rfc2549.org> | 2014-11-26 00:28:48 +0100 | 
| commit | 19e013e6ba85ee25817829bb6556ecd4776c704e (patch) | |
| tree | 8fd2650b23e0503e36da7e084be0cc2f4593f0b4 | |
| parent | 5dc503314511f3041b4674569ba03c10714f7625 (diff) | |
Update peer-id patch, remove now uneded code from OpenVPN for local block/unblock
--HG--
extra : rebase_source : 8a0eedbd74cb76ac50431f8c8b9bfdd42bc4a243
21 files changed, 258 insertions, 242 deletions
diff --git a/main/openvpn/config-version.h b/main/openvpn/config-version.h index 46896cbf..ca6f995f 100644 --- a/main/openvpn/config-version.h +++ b/main/openvpn/config-version.h @@ -1,2 +1,2 @@ -#define CONFIGURE_GIT_REVISION "icsopenvpn_623-cdf7ba7b109ff649" +#define CONFIGURE_GIT_REVISION "icsopenvpn_623-b18153d535847b6d"  #define CONFIGURE_GIT_FLAGS "" diff --git a/main/openvpn/distro/systemd/openvpn@.service b/main/openvpn/distro/systemd/openvpn-client@.service index 7cd36c36..56d93a93 100644 --- a/main/openvpn/distro/systemd/openvpn@.service +++ b/main/openvpn/distro/systemd/openvpn-client@.service @@ -1,6 +1,7 @@  [Unit]  Description=OpenVPN tunnel for %I -After=syslog.target network.target +After=syslog.target network-online.target +Wants=network-online.target  Documentation=man:openvpn(8)  Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage  Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO @@ -8,8 +9,8 @@ Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO  [Service]  PrivateTmp=true  Type=forking -PIDFile=/var/run/openvpn/%i.pid -ExecStart=/usr/sbin/openvpn --daemon --writepid /var/run/openvpn/%i.pid --cd /etc/openvpn/ --config %i.conf +PIDFile=/var/run/openvpn/client_%i.pid +ExecStart=/usr/sbin/openvpn --cd /etc/openvpn/client --config %i.conf --daemon --writepid /var/run/openvpn/client_%i.pid  CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH  LimitNPROC=10  DeviceAllow=/dev/null rw diff --git a/main/openvpn/distro/systemd/openvpn-server@.service b/main/openvpn/distro/systemd/openvpn-server@.service new file mode 100644 index 00000000..c4c9a123 --- /dev/null +++ b/main/openvpn/distro/systemd/openvpn-server@.service @@ -0,0 +1,19 @@ +[Unit] +Description=OpenVPN service for %I +After=syslog.target network.target +Documentation=man:openvpn(8) +Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage +Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO + +[Service] +PrivateTmp=true +Type=forking +PIDFile=/var/run/openvpn/server_%i.pid +ExecStart=/usr/sbin/openvpn --cd /etc/openvpn/server --status /var/run/openvpn/server_%i-status.log --status-version 2 --config %i.conf --daemon --writepid /var/run/openvpn/server_%i.pid +CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH +LimitNPROC=10 +DeviceAllow=/dev/null rw +DeviceAllow=/dev/net/tun rw + +[Install] +WantedBy=multi-user.target diff --git a/main/openvpn/doc/openvpn.8 b/main/openvpn/doc/openvpn.8 index 8fca9aa4..96ba5554 100644 --- a/main/openvpn/doc/openvpn.8 +++ b/main/openvpn/doc/openvpn.8 @@ -1437,6 +1437,7 @@ Currently defaults to 100.  Limit bandwidth of outgoing tunnel data to  .B n  bytes per second on the TCP/UDP port. +Note that this will only work if mode is set to p2p.  If you want to limit the bandwidth  in both directions, use this option on both peers. diff --git a/main/openvpn/src/openvpn/crypto.c b/main/openvpn/src/openvpn/crypto.c index 69df29de..ef2bde1d 100644 --- a/main/openvpn/src/openvpn/crypto.c +++ b/main/openvpn/src/openvpn/crypto.c @@ -223,30 +223,6 @@ err:    return;  } -int verify_hmac(struct buffer *buf, struct key_ctx *ctx, int offset) -{ -  uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ -  int hmac_len = 0; - -  hmac_ctx_reset(ctx->hmac); -  /* Assume the length of the input HMAC */ -  hmac_len = hmac_ctx_size (ctx->hmac); - -  /* Authentication fails if insufficient data in packet for HMAC */ -  if (buf->len - offset < hmac_len) -    return 0; - -  hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len + offset, -	BLEN (buf) - hmac_len - offset); -  hmac_ctx_final (ctx->hmac, local_hmac); - -  /* Compare locally computed HMAC with packet HMAC */ -  if (memcmp_constant_time (local_hmac, BPTR (buf) + offset, hmac_len) == 0) -    return hmac_len; - -  return 0; -} -  /*   * If (opt->flags & CO_USE_IV) is not NULL, we will read an IV from the packet.   * @@ -273,9 +249,25 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,        /* Verify the HMAC */        if (ctx->hmac)  	{ -	  int hmac_len = verify_hmac(buf, ctx, 0); -	  if (hmac_len == 0) +	  int hmac_len; +	  uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ + +	  hmac_ctx_reset(ctx->hmac); + +	  /* Assume the length of the input HMAC */ +	  hmac_len = hmac_ctx_size (ctx->hmac); + +	  /* Authentication fails if insufficient data in packet for HMAC */ +	  if (buf->len < hmac_len) +	    CRYPT_ERROR ("missing authentication info"); + +	  hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len, BLEN (buf) - hmac_len); +	  hmac_ctx_final (ctx->hmac, local_hmac); + +	  /* Compare locally computed HMAC with packet HMAC */ +	  if (memcmp_constant_time (local_hmac, BPTR (buf), hmac_len))  	    CRYPT_ERROR ("packet HMAC authentication failed"); +  	  ASSERT (buf_advance (buf, hmac_len));  	} @@ -400,28 +392,6 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,  }  /* - * This verifies if a packet and its HMAC fit to a crypto context. - * - * On success true is returned. - */ -bool -crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt) -{ -  if (buf->len > 0 && opt->key_ctx_bi) -    { -      struct key_ctx *ctx = &opt->key_ctx_bi->decrypt; - -      /* Verify the HMAC */ -      if (ctx->hmac) -	{ -	  /* sizeof(uint32_t) comes from peer_id (3 bytes) and opcode (1 byte) */ -	  return verify_hmac(buf, ctx, sizeof(uint32_t)) != 0; -	} -    } -  return false; -} - -/*   * How many bytes will we add to frame buffer for a given   * set of crypto options?   */ diff --git a/main/openvpn/src/openvpn/crypto.h b/main/openvpn/src/openvpn/crypto.h index 3c4e59d7..bf2f8028 100644 --- a/main/openvpn/src/openvpn/crypto.h +++ b/main/openvpn/src/openvpn/crypto.h @@ -275,9 +275,6 @@ bool openvpn_decrypt (struct buffer *buf, struct buffer work,  		      const struct crypto_options *opt,  		      const struct frame* frame); - -bool crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt); -  /** @} name Functions for performing security operations on data channel packets */  void crypto_adjust_frame_parameters(struct frame *frame, diff --git a/main/openvpn/src/openvpn/forward.c b/main/openvpn/src/openvpn/forward.c index 0bbdedb0..5709ee51 100644 --- a/main/openvpn/src/openvpn/forward.c +++ b/main/openvpn/src/openvpn/forward.c @@ -722,20 +722,11 @@ read_incoming_link (struct context *c)    perf_pop ();  } -/* - * Input:  c->c2.buf - * Output: c->c2.to_tun - */ - -void -process_incoming_link (struct context *c) +bool +process_incoming_link_part1 (struct context *c, struct link_socket_info *lsi, bool floated)  {    struct gc_arena gc = gc_new (); -  bool decrypt_status; -  struct link_socket_info *lsi = get_link_socket_info (c); -  const uint8_t *orig_buf = c->c2.buf.data; - -  perf_push (PERF_PROC_IN_LINK); +  bool decrypt_status = false;    if (c->c2.buf.len > 0)      { @@ -805,7 +796,7 @@ process_incoming_link (struct context *c)  	   * will load crypto_options with the correct encryption key  	   * and return false.  	   */ -	  if (tls_pre_decrypt (c->c2.tls_multi, &c->c2.from, &c->c2.buf, &c->c2.crypto_options)) +	  if (tls_pre_decrypt (c->c2.tls_multi, &c->c2.from, &c->c2.buf, &c->c2.crypto_options, floated))  	    {  	      interval_action (&c->c2.tmp_int); @@ -832,11 +823,25 @@ process_incoming_link (struct context *c)  	  /* decryption errors are fatal in TCP mode */  	  register_signal (c, SIGUSR1, "decryption-error"); /* SOFT-SIGUSR1 -- decryption error in TCP mode */  	  msg (D_STREAM_ERRORS, "Fatal decryption error (process_incoming_link), restarting"); -	  goto done;  	} - +#else /* ENABLE_CRYPTO */ +      decrypt_status = true;  #endif /* ENABLE_CRYPTO */ +    } +  else +    { +      buf_reset (&c->c2.to_tun); +    } +  gc_free (&gc); +  return decrypt_status; +} + +void +process_incoming_link_part2 (struct context *c, struct link_socket_info *lsi, const uint8_t *orig_buf) +{ +  if (c->c2.buf.len > 0) +    {  #ifdef ENABLE_FRAGMENT        if (c->c2.fragment)  	fragment_incoming (c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment); @@ -903,9 +908,20 @@ process_incoming_link (struct context *c)      {        buf_reset (&c->c2.to_tun);      } - done: +} + +void +process_incoming_link (struct context *c) +{ +  perf_push (PERF_PROC_IN_LINK); + +  struct link_socket_info *lsi = get_link_socket_info (c); +  const uint8_t *orig_buf = c->c2.buf.data; + +  process_incoming_link_part1(c, lsi, false); +  process_incoming_link_part2(c, lsi, orig_buf); +    perf_pop (); -  gc_free (&gc);  }  /* diff --git a/main/openvpn/src/openvpn/forward.h b/main/openvpn/src/openvpn/forward.h index 1830a00b..af3b0a67 100644 --- a/main/openvpn/src/openvpn/forward.h +++ b/main/openvpn/src/openvpn/forward.h @@ -127,12 +127,11 @@ void encrypt_sign (struct context *c, bool comp_frag);   */  void read_incoming_link (struct context *c); -  /** - * Process a packet read from the external network interface. + * Starts processing a packet read from the external network interface.   * @ingroup external_multiplexer   * - * This function controls the processing of a data channel packet which + * This function starts the processing of a data channel packet which   * has come out of a VPN tunnel.  It's high-level structure is as follows:   * - Verify that a nonzero length packet has been received from a valid   *   source address for the given context \a c. @@ -146,6 +145,25 @@ void read_incoming_link (struct context *c);   * - Call \c openvpn_decrypt() of the \link data_crypto Data Channel   *   Crypto module\endlink to authenticate and decrypt the packet using   *   the security parameters loaded by \c tls_pre_decrypt() above. + * + * @param c - The context structure of the VPN tunnel associated with the + *     packet. + * @param lsi - link_socket_info obtained from context before processing. + * @param floated - Flag indicates that peer has floated. + * + * @return true if packet is authenticated, false otherwise. + */ +bool process_incoming_link_part1 (struct context *c, struct link_socket_info *lsi, bool floated); + +/** + * Continues processing a packet read from the external network interface. + * @ingroup external_multiplexer + * + * This function continues the processing of a data channel packet which + * has come out of a VPN tunnel. It must be called after + * \c process_incoming_link_part1() function. + * + * It's high-level structure is as follows:   * - Call \c fragment_incoming() of the \link fragmentation Data Channel   *   Fragmentation module\endlink to reassemble the packet if it's   *   fragmented. @@ -158,9 +176,11 @@ void read_incoming_link (struct context *c);   *   * @param c - The context structure of the VPN tunnel associated with the   *     packet. + * @param lsi - link_socket_info obtained from context before processing. + * @param orig_buf - Pointer to a buffer data. + *   */ -void process_incoming_link (struct context *c); - +void process_incoming_link_part2 (struct context *c, struct link_socket_info *lsi, const uint8_t *orig_buf);  /**   * Write a packet to the external network interface. diff --git a/main/openvpn/src/openvpn/init.c b/main/openvpn/src/openvpn/init.c index 7cec8d9b..b5c81f87 100644 --- a/main/openvpn/src/openvpn/init.c +++ b/main/openvpn/src/openvpn/init.c @@ -1797,12 +1797,14 @@ do_deferred_options (struct context *c, const unsigned int found)    if (found & OPT_P_SETENV)      msg (D_PUSH, "OPTIONS IMPORT: environment modified"); +#ifdef ENABLE_SSL    if (found & OPT_P_PEER_ID)      {        msg (D_PUSH, "OPTIONS IMPORT: peer-id set");        c->c2.tls_multi->use_peer_id = true;        c->c2.tls_multi->peer_id = c->options.peer_id;      } +#endif  }  /* diff --git a/main/openvpn/src/openvpn/mudp.c b/main/openvpn/src/openvpn/mudp.c index 51227a90..853c08ce 100644 --- a/main/openvpn/src/openvpn/mudp.c +++ b/main/openvpn/src/openvpn/mudp.c @@ -33,67 +33,19 @@  #if P2MP_SERVER  #include "multi.h" +#include <inttypes.h>  #include "forward-inline.h"  #include "memdbg.h"  /* - * Update instance with new peer address - */ -void -update_floated(struct multi_context *m, struct multi_instance *mi, -	       struct mroute_addr real, uint32_t hv) -{ -  struct mroute_addr real_old; - -  real_old = mi->real; -  generate_prefix (mi); - -  /* remove before modifying mi->real, since it also modifies key in hash */ -  hash_remove(m->hash, &real_old); -  hash_remove(m->iter, &real_old); - -  /* update address */ -  memcpy(&mi->real, &real, sizeof(real)); - -  mi->context.c2.from = m->top.c2.from; -  mi->context.c2.to_link_addr = &mi->context.c2.from; - -  /* switch to new log prefix */ -  generate_prefix (mi); -  /* inherit buffers */ -  mi->context.c2.buffers = m->top.c2.buffers; - -  /* inherit parent link_socket and link_socket_info */ -  mi->context.c2.link_socket = m->top.c2.link_socket; -  mi->context.c2.link_socket_info->lsa->actual = m->top.c2.from; - -  /* fix remote_addr in tls structure */ -  tls_update_remote_addr (mi->context.c2.tls_multi, &mi->context.c2.from); -  mi->did_open_context = true; - -  hash_add(m->hash, &mi->real, mi, false); -  hash_add(m->iter, &mi->real, mi, false); - -  mi->did_real_hash = true; -#ifdef MANAGEMENT_DEF_AUTH -  hash_remove (m->cid_hash, &mi->context.c2.mda_context.cid); -  hash_add (m->cid_hash, &mi->context.c2.mda_context.cid, mi, false); -#endif - -#ifdef MANAGEMENT_DEF_AUTH -  mi->did_cid_hash = true; -#endif -} - -/*   * Get a client instance based on real address.  If   * the instance doesn't exist, create it while   * maintaining real address hash table atomicity.   */  struct multi_instance * -multi_get_create_instance_udp (struct multi_context *m) +multi_get_create_instance_udp (struct multi_context *m, bool *floated)  {    struct gc_arena gc = gc_new ();    struct mroute_addr real; @@ -108,32 +60,25 @@ multi_get_create_instance_udp (struct multi_context *m)        uint8_t* ptr = BPTR(&m->top.c2.buf);        uint8_t op = ptr[0] >> P_OPCODE_SHIFT;        uint32_t peer_id; -      bool hmac_mismatch = false; +      int i; -      if (op == P_DATA_V2) +      /* make sure buffer has enough length to read opcode (1 byte) and peer-id (3 bytes) */ +      if (op == P_DATA_V2 && m->top.c2.buf.len >= (1 + 3))  	{ -	  peer_id = ntohl((*(uint32_t*)ptr)) & 0xFFFFFF; +	  peer_id = ntohl(*(uint32_t*)ptr) & 0xFFFFFF;  	  if ((peer_id < m->max_clients) && (m->instances[peer_id]))  	    {  	      mi = m->instances[peer_id]; -	      if (!link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from)) -		{ -		  msg(D_MULTI_MEDIUM, "float from %s to %s", -			print_link_socket_actual (&mi->context.c2.from, &gc), print_link_socket_actual (&m->top.c2.from, &gc)); +	      *floated = !link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from); -		  /* peer-id is not trusted, so check hmac */ -		  hmac_mismatch = !(crypto_test_hmac(&m->top.c2.buf, &mi->context.c2.crypto_options)); -		  if (hmac_mismatch) -		    { -		      mi = NULL; -		      msg (D_MULTI_MEDIUM, "HMAC mismatch for peer-id %d", peer_id); -		    } -		  else -		    { -		      update_floated(m, mi, real, hv); -		    } -		} +	      if (*floated) +	      { +		/* reset prefix, since here we are not sure peer is the one it claims to be */ +		ungenerate_prefix(mi); +		msg (D_MULTI_ERRORS, "Untrusted peer %" PRIu32 " wants to float to %s", peer_id, +			mroute_addr_print (&real, &gc)); +	      }  	    }  	}        else @@ -144,7 +89,7 @@ multi_get_create_instance_udp (struct multi_context *m)  	      mi = (struct multi_instance *) he->value;  	    }  	} -      if (!mi && !hmac_mismatch) +      if (!mi)  	{  	  if (!m->top.c2.tls_auth_standalone  	      || tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf)) @@ -157,8 +102,7 @@ multi_get_create_instance_udp (struct multi_context *m)  		      hash_add_fast (hash, bucket, &mi->real, hv, mi);  		      mi->did_real_hash = true; -		      int i; -		      for (i = 0; i < m->max_clients; ++ i) +		      for (i = 0; i < m->max_clients; ++i)  			{  			  if (!m->instances[i])  			    { diff --git a/main/openvpn/src/openvpn/mudp.h b/main/openvpn/src/openvpn/mudp.h index 97f961b3..1f15d9d2 100644 --- a/main/openvpn/src/openvpn/mudp.h +++ b/main/openvpn/src/openvpn/mudp.h @@ -65,7 +65,7 @@ void tunnel_server_udp (struct context *top);   *     packet's source address or if one was a newly created successfully.   *      NULL if one did not yet exist and a new one was not created.   */ -struct multi_instance *multi_get_create_instance_udp (struct multi_context *m); +struct multi_instance *multi_get_create_instance_udp (struct multi_context *m, bool *floated);  #endif  #endif diff --git a/main/openvpn/src/openvpn/multi.c b/main/openvpn/src/openvpn/multi.c index bd5948c8..a4334b20 100644 --- a/main/openvpn/src/openvpn/multi.c +++ b/main/openvpn/src/openvpn/multi.c @@ -39,6 +39,7 @@  #include "gremlin.h"  #include "mstats.h"  #include "ssl_verify.h" +#include <inttypes.h>  #include "memdbg.h" @@ -2104,6 +2105,70 @@ multi_process_post (struct multi_context *m, struct multi_instance *mi, const un    return ret;  } +void multi_process_float (struct multi_context* m, struct multi_instance* mi) +{ +  struct mroute_addr real; +  struct hash *hash = m->hash; +  struct gc_arena gc = gc_new (); + +  if (!mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true)) +    goto done; + +  const uint32_t hv = hash_value (hash, &real); +  struct hash_bucket *bucket = hash_bucket (hash, hv); + +  struct hash_element *he = hash_lookup_fast (hash, bucket, &real, hv); +  if (he) +    { +      struct multi_instance *ex_mi = (struct multi_instance *) he->value; + +      const char *cn = tls_common_name (mi->context.c2.tls_multi, true); +      const char *ex_cn = tls_common_name (ex_mi->context.c2.tls_multi, true); +      if (cn && ex_cn && strcmp (cn, ex_cn)) +	{ +	  msg (D_MULTI_MEDIUM, "prevent float to %s", +		multi_instance_string (ex_mi, false, &gc)); + +	  mi->context.c2.buf.len = 0; + +	  goto done; +	} + +      msg (D_MULTI_MEDIUM, "closing instance %s", multi_instance_string (ex_mi, false, &gc)); +      multi_close_instance(m, ex_mi, false); +    } + +    msg (D_MULTI_MEDIUM, "peer %" PRIu32 " floated from %s to %s", mi->context.c2.tls_multi->peer_id, +        mroute_addr_print (&mi->real, &gc), print_link_socket_actual (&m->top.c2.from, &gc)); + +    ASSERT (hash_remove(m->hash, &mi->real)); +    ASSERT (hash_remove(m->iter, &mi->real)); + +    /* change external network address of the remote peer */ +    mi->real = real; +    generate_prefix (mi); + +    mi->context.c2.from = m->top.c2.from; +    mi->context.c2.to_link_addr = &mi->context.c2.from; + +    /* inherit parent link_socket and link_socket_info */ +    mi->context.c2.link_socket = m->top.c2.link_socket; +    mi->context.c2.link_socket_info->lsa->actual = m->top.c2.from; + +    tls_update_remote_addr (mi->context.c2.tls_multi, &mi->context.c2.from); + +    ASSERT (hash_add (m->hash, &mi->real, mi, false)); +    ASSERT (hash_add (m->iter, &mi->real, mi, false)); + +#ifdef MANAGEMENT_DEF_AUTH +    hash_remove (m->cid_hash, &mi->context.c2.mda_context.cid); +    hash_add (m->cid_hash, &mi->context.c2.mda_context.cid, mi, false); +#endif + +done: +    gc_free (&gc); +} +  /*   * Process packets in the TCP/UDP socket -> TUN/TAP interface direction,   * i.e. client -> server direction. @@ -2118,6 +2183,7 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins    unsigned int mroute_flags;    struct multi_instance *mi;    bool ret = true; +  bool floated = false;    if (m->pending)      return true; @@ -2127,7 +2193,7 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins  #ifdef MULTI_DEBUG_EVENT_LOOP        printf ("TCP/UDP -> TUN [%d]\n", BLEN (&m->top.c2.buf));  #endif -      multi_set_pending (m, multi_get_create_instance_udp (m)); +      multi_set_pending (m, multi_get_create_instance_udp (m, &floated));      }    else      multi_set_pending (m, instance); @@ -2145,13 +2211,30 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins  	  c->c2.buf = m->top.c2.buf;  	  /* transfer from-addr from top-level context buffer to instance */ -	  c->c2.from = m->top.c2.from; +	  if (!floated) +	    c->c2.from = m->top.c2.from;  	}        if (BLEN (&c->c2.buf) > 0)  	{ +	  struct link_socket_info *lsi; +	  const uint8_t *orig_buf; +  	  /* decrypt in instance context */ -	  process_incoming_link (c); + +	  perf_push (PERF_PROC_IN_LINK); +	  lsi = get_link_socket_info (c); +	  orig_buf = c->c2.buf.data; +	  if (process_incoming_link_part1(c, lsi, floated)) +	    { +	      if (floated) +		{ +		  multi_process_float (m, m->pending); +		} + +	      process_incoming_link_part2(c, lsi, orig_buf); +	    } +	  perf_pop ();  	  if (TUNNEL_TYPE (m->top.c1.tuntap) == DEV_TYPE_TUN)  	    { diff --git a/main/openvpn/src/openvpn/multi.h b/main/openvpn/src/openvpn/multi.h index 0446fbfc..ad7f7001 100644 --- a/main/openvpn/src/openvpn/multi.h +++ b/main/openvpn/src/openvpn/multi.h @@ -125,7 +125,8 @@ struct multi_context {  # define MC_WORK_THREAD                (MC_MULTI_THREADED_WORKER|MC_MULTI_THREADED_SCHEDULER)    int thread_mode; -  struct multi_instance** instances; +  struct multi_instance** instances;    /**< Array of multi_instances. An instance can be +                                         * accessed using peer-id as an index. */    struct hash *hash;            /**< VPN tunnel instances indexed by real                                   *   address of the remote peer. */ @@ -220,6 +221,16 @@ void multi_close_instance (struct multi_context *m, struct multi_instance *mi, b  bool multi_process_timeout (struct multi_context *m, const unsigned int mpp_flags); +/** + * Handles peer floating. + * + * If peer is floated to a taken address, either drops packet + * (if peer that owns address has different CN) or disconnects + * existing peer. Updates multi_instance with new address, + * updates hashtables in multi_context. + */ +void multi_process_float (struct multi_context* m, struct multi_instance* mi); +  #define MPP_PRE_SELECT             (1<<0)  #define MPP_CONDITIONAL_PRE_SELECT (1<<1)  #define MPP_CLOSE_ON_SIGNAL        (1<<2) @@ -421,6 +432,12 @@ multi_route_defined (const struct multi_context *m,  }  /* + * Takes prefix away from multi_instance. + */ +void +ungenerate_prefix (struct multi_instance *mi); + +/*   * Set a msg() function prefix with our current client instance ID.   */ diff --git a/main/openvpn/src/openvpn/options.c b/main/openvpn/src/openvpn/options.c index 03e5e55e..e096bec2 100644 --- a/main/openvpn/src/openvpn/options.c +++ b/main/openvpn/src/openvpn/options.c @@ -1977,9 +1977,6 @@ options_postprocess_verify_ce (const struct options *options, const struct conne    if (ce->proto == PROTO_TCP_SERVER && (options->connection_list->len > 1))      msg (M_USAGE, "TCP server mode allows at most one --remote address"); -  if (options->routes && ((options->routes->flags & RG_BLOCK_LOCAL) && (options->routes->flags & RG_UNBLOCK_LOCAL))) -    msg (M_USAGE, "unblock-local and block-local options of redirect-gateway/redirect-private are mutatlly exclusive"); -  #if P2MP_SERVER    /* @@ -2039,7 +2036,6 @@ options_postprocess_verify_ce (const struct options *options, const struct conne  #endif        if (options->routes && (options->routes->flags & RG_ENABLE))  	msg (M_USAGE, "--redirect-gateway cannot be used with --mode server (however --push \"redirect-gateway\" is fine)"); -        if (options->route_delay_defined)  	msg (M_USAGE, "--route-delay cannot be used with --mode server");        if (options->up_delay) @@ -3899,8 +3895,7 @@ apply_push_options (struct options *options,  		    struct buffer *buf,  		    unsigned int permission_mask,  		    unsigned int *option_types_found, -		    struct env_set *es, -		    struct tls_multi *tls_multi) +		    struct env_set *es)  {    char line[OPTION_PARM_SIZE];    int line_num = 0; @@ -5326,8 +5321,6 @@ add_option (struct options *options,  	    options->routes->flags |= RG_BYPASS_DNS;  	  else if (streq (p[j], "block-local"))  	    options->routes->flags |= RG_BLOCK_LOCAL; -	  else if (streq (p[j], "unblock-local")) -	    options->routes->flags |= RG_UNBLOCK_LOCAL;  	  else  	    {  	      msg (msglevel, "unknown --%s flag: %s", p[0], p[j]); diff --git a/main/openvpn/src/openvpn/options.h b/main/openvpn/src/openvpn/options.h index d5f7e95d..a51b8ab5 100644 --- a/main/openvpn/src/openvpn/options.h +++ b/main/openvpn/src/openvpn/options.h @@ -716,13 +716,11 @@ void options_postprocess (struct options *options);  void pre_pull_save (struct options *o);  void pre_pull_restore (struct options *o, struct gc_arena *gc); -struct tls_multi;  bool apply_push_options (struct options *options,  			 struct buffer *buf,  			 unsigned int permission_mask,  			 unsigned int *option_types_found, -			 struct env_set *es, -			 struct tls_multi* tls_multi); +			 struct env_set *es);  void options_detach (struct options *o); diff --git a/main/openvpn/src/openvpn/push.c b/main/openvpn/src/openvpn/push.c index c7844499..385be1d5 100644 --- a/main/openvpn/src/openvpn/push.c +++ b/main/openvpn/src/openvpn/push.c @@ -475,8 +475,7 @@ process_incoming_push_msg (struct context *c,  				  &buf,  				  permission_mask,  				  option_types_found, -				  c->c2.es, -				  c->c2.tls_multi)) +				  c->c2.es))  	    switch (c->options.push_continuation)  	      {  	      case 0: diff --git a/main/openvpn/src/openvpn/route.c b/main/openvpn/src/openvpn/route.c index 8828bff3..1cb98c03 100644 --- a/main/openvpn/src/openvpn/route.c +++ b/main/openvpn/src/openvpn/route.c @@ -520,51 +520,6 @@ add_block_local_item (struct route_list *rl,  }  static void -add_unblock_local (struct route_list *rl) -{ -  const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED); - -  if (rl->flags & RG_UNBLOCK_LOCAL -      && (rl->rgi.flags & rgi_needed) == rgi_needed) -    { -      /* unblock access to local subnet */ -      struct route_ipv4 *r; - -      ALLOC_OBJ_GC (r, struct route_ipv4, &rl->gc); -      int i; - -      CLEAR(*r); -      r->flags = RT_DEFINED; -      r->network = rl->rgi.gateway.addr & rl->rgi.gateway.netmask; -      r->netmask = rl->rgi.gateway.netmask; -      r->gateway = rl->rgi.gateway.addr; -      r->next = rl->routes; -      rl->routes = r; - -      /* Additional local networks */ -      for (i = 0; i < rl->rgi.n_addrs; ++i) -	{ -	  const struct route_gateway_address *gwa = &rl->rgi.addrs[i]; - -	  /* omit the add/subnet in &rl->rgi which we processed above */ -	  if (!((rl->rgi.gateway.addr & rl->rgi.gateway.netmask) == (gwa->addr & gwa->netmask) -		 && rl->rgi.gateway.netmask == gwa->netmask)) -	    { -	      ALLOC_OBJ_GC (r, struct route_ipv4, &rl->gc); -	      CLEAR(*r); -	      r->flags = RT_DEFINED; -	      r->network = gwa->addr & gwa->netmask; -	      r->netmask = gwa->netmask; -	      r->gateway = gwa->addr; -	      r->next = rl->routes; -	      rl->routes=r; -	    } -	} -    } -} - - -static void  add_block_local (struct route_list *rl)  {    const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED); @@ -595,8 +550,6 @@ add_block_local (struct route_list *rl)      }  } - -  bool  init_route_list (struct route_list *rl,  		 const struct route_option_list *opt, @@ -665,8 +618,6 @@ init_route_list (struct route_list *rl,  	}      } - -  add_unblock_local (rl);    if (rl->flags & RG_ENABLE)      {        add_block_local (rl); @@ -863,12 +814,10 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u  	{  	  msg (M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);  	} -#ifndef TARGET_ANDROID        else if (!(rl->rgi.flags & RGI_ADDR_DEFINED))  	{  	  msg (M_WARN, "%s Cannot read current default gateway from system", err);  	} -#endif        else if (!(rl->spec.flags & RTSA_REMOTE_HOST))  	{  	  msg (M_WARN, "%s Cannot obtain current remote host address", err); @@ -2599,7 +2548,7 @@ get_default_gateway (struct route_gateway_info *rgi)    /* Android, set some pseudo GW, addr is in host byte order */    rgi->gateway.addr = 127 << 24 | 'd' << 16 | 'g' << 8 | 'w';    rgi->flags |= RGI_ADDR_DEFINED; -  best_name = "android-default"; +  strcpy(best_name, "android-gw");  #endif    /* scan adapter list */ diff --git a/main/openvpn/src/openvpn/route.h b/main/openvpn/src/openvpn/route.h index 2b1ae3e8..f3c01501 100644 --- a/main/openvpn/src/openvpn/route.h +++ b/main/openvpn/src/openvpn/route.h @@ -88,7 +88,6 @@ struct route_option {  #define RG_REROUTE_GW     (1<<5)  #define RG_AUTO_LOCAL     (1<<6)  #define RG_BLOCK_LOCAL    (1<<7) -#define RG_UNBLOCK_LOCAL    (1<<8)  struct route_option_list {    unsigned int flags;  /* RG_x flags */ diff --git a/main/openvpn/src/openvpn/ssl.c b/main/openvpn/src/openvpn/ssl.c index d298adde..2adfa26f 100644 --- a/main/openvpn/src/openvpn/ssl.c +++ b/main/openvpn/src/openvpn/ssl.c @@ -2773,7 +2773,8 @@ bool  tls_pre_decrypt (struct tls_multi *multi,  		 const struct link_socket_actual *from,  		 struct buffer *buf, -		 struct crypto_options *opt) +		 struct crypto_options *opt, +		 bool floated)  {    struct gc_arena gc = gc_new ();    bool ret = false; @@ -2817,7 +2818,7 @@ tls_pre_decrypt (struct tls_multi *multi,  #ifdef ENABLE_DEF_AUTH  		  && !ks->auth_deferred  #endif -		  && link_socket_actual_match (from, &ks->remote_addr)) +		  && (floated || link_socket_actual_match (from, &ks->remote_addr)))  		{  		  /* return appropriate data channel decrypt key in opt */  		  opt->key_ctx_bi = &ks->key; @@ -3492,27 +3493,30 @@ tls_rec_payload (struct tls_multi *multi,    return ret;  } -/* Update the remote_addr, needed if a client floats. */  void -tls_update_remote_addr (struct tls_multi *multi, -const struct link_socket_actual *from) +tls_update_remote_addr (struct tls_multi *multi, const struct link_socket_actual *addr)  {    struct gc_arena gc = gc_new (); -  int i; +  int i, j; -  for (i = 0; i < KEY_SCAN_SIZE; ++i) +  for (i = 0; i < TM_SIZE; ++i)      { -      struct key_state *ks = multi->key_scan[i]; -      if (DECRYPT_KEY_ENABLED (multi, ks) && ks->authenticated && link_socket_actual_defined(&ks->remote_addr)) -       { -	 if (link_socket_actual_match (from, &ks->remote_addr)) -	   continue; -	 dmsg (D_TLS_KEYSELECT, -		"TLS: tls_update_remote_addr from IP=%s to IP=%s", +      struct tls_session *session = &multi->session[i]; + +      for (j = 0; j < KS_SIZE; ++j) +	{ +	  struct key_state *ks = &session->key[j]; + +	  if (!link_socket_actual_defined(&ks->remote_addr) || +		link_socket_actual_match (addr, &ks->remote_addr)) +	    continue; + +	  dmsg (D_TLS_KEYSELECT, "TLS: tls_update_remote_addr from IP=%s to IP=%s",  	       print_link_socket_actual (&ks->remote_addr, &gc), -	       print_link_socket_actual (from, &gc)); -	 memcpy(&ks->remote_addr, from, sizeof(*from)); -       } +	       print_link_socket_actual (addr, &gc)); + +	  ks->remote_addr = *addr; +	}      }    gc_free (&gc);  } diff --git a/main/openvpn/src/openvpn/ssl.h b/main/openvpn/src/openvpn/ssl.h index a338745e..7e5a203e 100644 --- a/main/openvpn/src/openvpn/ssl.h +++ b/main/openvpn/src/openvpn/ssl.h @@ -306,7 +306,8 @@ int tls_multi_process (struct tls_multi *multi,  bool tls_pre_decrypt (struct tls_multi *multi,  		      const struct link_socket_actual *from,  		      struct buffer *buf, -		      struct crypto_options *opt); +		      struct crypto_options *opt, +		      bool floated);  /**************************************************************************/ @@ -431,11 +432,14 @@ bool tls_send_payload (struct tls_multi *multi,  bool tls_rec_payload (struct tls_multi *multi,  		      struct buffer *buf); -/* - * Update remote address of a tls_multi structure +/** + * Updates remote address in TLS sessions. + * + * @param multi - Tunnel to update + * @param addr - new address   */  void tls_update_remote_addr (struct tls_multi *multi, -			     const struct link_socket_actual *from); +			     const struct link_socket_actual *addr);  #ifdef MANAGEMENT_DEF_AUTH  static inline char * diff --git a/main/openvpn/src/openvpn/ssl_polarssl.c b/main/openvpn/src/openvpn/ssl_polarssl.c index b026a17b..20368857 100644 --- a/main/openvpn/src/openvpn/ssl_polarssl.c +++ b/main/openvpn/src/openvpn/ssl_polarssl.c @@ -846,8 +846,8 @@ key_state_write_plaintext (struct key_state_ssl *ks, struct buffer *buf)    if (0 == buf->len)      { -      return 0;        perf_pop (); +      return 0;      }    retval = ssl_write(ks->ctx, BPTR(buf), buf->len);  | 
