summaryrefslogtreecommitdiff
path: root/app/openvpn/src/openvpn/mudp.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/openvpn/src/openvpn/mudp.c')
-rw-r--r--app/openvpn/src/openvpn/mudp.c92
1 files changed, 20 insertions, 72 deletions
diff --git a/app/openvpn/src/openvpn/mudp.c b/app/openvpn/src/openvpn/mudp.c
index 51227a90..3e3f7508 100644
--- a/app/openvpn/src/openvpn/mudp.c
+++ b/app/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])
{
@@ -167,6 +111,10 @@ multi_get_create_instance_udp (struct multi_context *m)
break;
}
}
+
+ /* should not really end up here, since multi_create_instance returns null
+ * if amount of clients exceeds max_clients */
+ ASSERT(i < m->max_clients);
}
}
else