From 19e013e6ba85ee25817829bb6556ecd4776c704e Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Wed, 26 Nov 2014 00:28:48 +0100 Subject: Update peer-id patch, remove now uneded code from OpenVPN for local block/unblock --HG-- extra : rebase_source : 8a0eedbd74cb76ac50431f8c8b9bfdd42bc4a243 --- main/openvpn/config-version.h | 2 +- .../openvpn/distro/systemd/openvpn-client@.service | 20 +++++ .../openvpn/distro/systemd/openvpn-server@.service | 19 +++++ main/openvpn/distro/systemd/openvpn@.service | 19 ----- main/openvpn/doc/openvpn.8 | 1 + main/openvpn/src/openvpn/crypto.c | 66 +++++----------- main/openvpn/src/openvpn/crypto.h | 3 - main/openvpn/src/openvpn/forward.c | 50 +++++++----- main/openvpn/src/openvpn/forward.h | 30 ++++++-- main/openvpn/src/openvpn/init.c | 2 + main/openvpn/src/openvpn/mudp.c | 88 ++++----------------- main/openvpn/src/openvpn/mudp.h | 2 +- main/openvpn/src/openvpn/multi.c | 89 +++++++++++++++++++++- main/openvpn/src/openvpn/multi.h | 19 ++++- main/openvpn/src/openvpn/options.c | 9 +-- main/openvpn/src/openvpn/options.h | 4 +- main/openvpn/src/openvpn/push.c | 3 +- main/openvpn/src/openvpn/route.c | 53 +------------ main/openvpn/src/openvpn/route.h | 1 - main/openvpn/src/openvpn/ssl.c | 38 ++++----- main/openvpn/src/openvpn/ssl.h | 12 ++- main/openvpn/src/openvpn/ssl_polarssl.c | 2 +- 22 files changed, 274 insertions(+), 258 deletions(-) create mode 100644 main/openvpn/distro/systemd/openvpn-client@.service create mode 100644 main/openvpn/distro/systemd/openvpn-server@.service delete mode 100644 main/openvpn/distro/systemd/openvpn@.service (limited to 'main/openvpn') 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-client@.service b/main/openvpn/distro/systemd/openvpn-client@.service new file mode 100644 index 00000000..56d93a93 --- /dev/null +++ b/main/openvpn/distro/systemd/openvpn-client@.service @@ -0,0 +1,20 @@ +[Unit] +Description=OpenVPN tunnel for %I +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 + +[Service] +PrivateTmp=true +Type=forking +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 +DeviceAllow=/dev/net/tun rw + +[Install] +WantedBy=multi-user.target 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/distro/systemd/openvpn@.service b/main/openvpn/distro/systemd/openvpn@.service deleted file mode 100644 index 7cd36c36..00000000 --- a/main/openvpn/distro/systemd/openvpn@.service +++ /dev/null @@ -1,19 +0,0 @@ -[Unit] -Description=OpenVPN tunnel 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/%i.pid -ExecStart=/usr/sbin/openvpn --daemon --writepid /var/run/openvpn/%i.pid --cd /etc/openvpn/ --config %i.conf -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)); } @@ -399,28 +391,6 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, return false; } -/* - * 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,59 +33,11 @@ #if P2MP_SERVER #include "multi.h" +#include #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 @@ -93,7 +45,7 @@ update_floated(struct multi_context *m, struct multi_instance *mi, */ 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 #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) @@ -420,6 +431,12 @@ multi_route_defined (const struct multi_context *m, return true; } +/* + * 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 @@ -519,51 +519,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) { @@ -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); -- cgit v1.2.3