summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2014-11-26 00:28:48 +0100
committerArne Schwabe <arne@rfc2549.org>2014-11-26 00:28:48 +0100
commit19e013e6ba85ee25817829bb6556ecd4776c704e (patch)
tree8fd2650b23e0503e36da7e084be0cc2f4593f0b4
parent5dc503314511f3041b4674569ba03c10714f7625 (diff)
Update peer-id patch, remove now uneded code from OpenVPN for local block/unblock
--HG-- extra : rebase_source : 8a0eedbd74cb76ac50431f8c8b9bfdd42bc4a243
-rw-r--r--main/openvpn/config-version.h2
-rw-r--r--main/openvpn/distro/systemd/openvpn-client@.service (renamed from main/openvpn/distro/systemd/openvpn@.service)7
-rw-r--r--main/openvpn/distro/systemd/openvpn-server@.service19
-rw-r--r--main/openvpn/doc/openvpn.81
-rw-r--r--main/openvpn/src/openvpn/crypto.c66
-rw-r--r--main/openvpn/src/openvpn/crypto.h3
-rw-r--r--main/openvpn/src/openvpn/forward.c50
-rw-r--r--main/openvpn/src/openvpn/forward.h30
-rw-r--r--main/openvpn/src/openvpn/init.c2
-rw-r--r--main/openvpn/src/openvpn/mudp.c88
-rw-r--r--main/openvpn/src/openvpn/mudp.h2
-rw-r--r--main/openvpn/src/openvpn/multi.c89
-rw-r--r--main/openvpn/src/openvpn/multi.h19
-rw-r--r--main/openvpn/src/openvpn/options.c9
-rw-r--r--main/openvpn/src/openvpn/options.h4
-rw-r--r--main/openvpn/src/openvpn/push.c3
-rw-r--r--main/openvpn/src/openvpn/route.c53
-rw-r--r--main/openvpn/src/openvpn/route.h1
-rw-r--r--main/openvpn/src/openvpn/ssl.c38
-rw-r--r--main/openvpn/src/openvpn/ssl.h12
-rw-r--r--main/openvpn/src/openvpn/ssl_polarssl.c2
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);