diff options
Diffstat (limited to 'src/openvpn/mudp.c')
-rw-r--r-- | src/openvpn/mudp.c | 57 |
1 files changed, 43 insertions, 14 deletions
diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index 3468dab..853c08c 100644 --- a/src/openvpn/mudp.c +++ b/src/openvpn/mudp.c @@ -33,6 +33,7 @@ #if P2MP_SERVER #include "multi.h" +#include <inttypes.h> #include "forward-inline.h" #include "memdbg.h" @@ -44,7 +45,7 @@ */ 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; @@ -56,15 +57,40 @@ multi_get_create_instance_udp (struct multi_context *m) struct hash_element *he; const uint32_t hv = hash_value (hash, &real); struct hash_bucket *bucket = hash_bucket (hash, hv); - - he = hash_lookup_fast (hash, bucket, &real, hv); + uint8_t* ptr = BPTR(&m->top.c2.buf); + uint8_t op = ptr[0] >> P_OPCODE_SHIFT; + uint32_t peer_id; + int i; - if (he) + /* 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)) { - mi = (struct multi_instance *) he->value; + peer_id = ntohl(*(uint32_t*)ptr) & 0xFFFFFF; + if ((peer_id < m->max_clients) && (m->instances[peer_id])) + { + mi = m->instances[peer_id]; + + *floated = !link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from); + + 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 { + he = hash_lookup_fast (hash, bucket, &real, hv); + if (he) + { + mi = (struct multi_instance *) he->value; + } + } + 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)) { @@ -75,6 +101,16 @@ multi_get_create_instance_udp (struct multi_context *m) { hash_add_fast (hash, bucket, &mi->real, hv, mi); mi->did_real_hash = true; + + for (i = 0; i < m->max_clients; ++i) + { + if (!m->instances[i]) + { + mi->context.c2.tls_multi->peer_id = i; + m->instances[i] = mi; + break; + } + } } } else @@ -89,15 +125,8 @@ multi_get_create_instance_udp (struct multi_context *m) #ifdef ENABLE_DEBUG if (check_debug_level (D_MULTI_DEBUG)) { - const char *status; - - if (he && mi) - status = "[succeeded]"; - else if (!he && mi) - status = "[created]"; - else - status = "[failed]"; - + const char *status = mi ? "[ok]" : "[failed]"; + dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s", mroute_addr_print (&real, &gc), status); |