Пример #1
0
struct multi_instance *
multi_get_create_instance_udp (struct multi_context *m)
{
  struct gc_arena gc = gc_new ();
  struct mroute_addr real;
  struct multi_instance *mi = NULL;
  struct hash *hash = m->hash;

  if (mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true))
    {
      struct hash_element *he;
      const uint32_t hv = hash_value (hash, &real);
      struct hash_bucket *bucket = hash_bucket (hash, hv);
      uint8_t* ptr  = BPTR(&m->top.c2.buf);
      uint8_t op = ptr[0] >> P_OPCODE_SHIFT;
      uint32_t sess_id;
      bool session_forged = false;

      if (op == P_DATA_V2)
	{
	  sess_id = (*(uint32_t*)ptr) >> 8;
	  if ((sess_id < m->max_clients) && (m->instances[sess_id]))
	    {
	      mi = m->instances[sess_id];

	      if (!link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from))
		{
		  msg(D_MULTI_MEDIUM, "floating detected from %s to %s",
		      print_link_socket_actual (&mi->context.c2.from, &gc), print_link_socket_actual (&m->top.c2.from, &gc));

		  /* session-id is not trusted, so check hmac */
		  session_forged = !(crypto_test_hmac(&m->top.c2.buf, &mi->context.c2.crypto_options));
		  if (session_forged)
		    {
		      mi = NULL;
		      msg (D_MULTI_MEDIUM, "hmac verification failed, session forge detected!");
		    }
		  else
		    {
		      update_floated(m, mi, real, hv);
		    }
		}
	    }
	}
      else
	{
Пример #2
0
struct multi_instance *
multi_get_create_instance_udp (struct multi_context *m, bool *floated)
{
  struct gc_arena gc = gc_new ();
  struct mroute_addr real;
  struct multi_instance *mi = NULL;
  struct hash *hash = m->hash;

  if (mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true) &&
      m->top.c2.buf.len > 0)
    {
      struct hash_element *he;
      const uint32_t hv = hash_value (hash, &real);
      struct hash_bucket *bucket = hash_bucket (hash, hv);
      uint8_t* ptr = BPTR(&m->top.c2.buf);
      uint8_t op = ptr[0] >> P_OPCODE_SHIFT;

      /* 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))
	{
	  uint32_t 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))
	    {
	      if (frequency_limit_event_allowed (m->new_connection_limiter))
		{
		  mi = multi_create_instance (m, &real);
		  if (mi)
		    {
		      int i;

		      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;
			    }
			}

		      /* 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
		{
		  msg (D_MULTI_ERRORS,
		       "MULTI: Connection from %s would exceed new connection frequency limit as controlled by --connect-freq",
		       mroute_addr_print (&real, &gc));
		}
	    }
	}

#ifdef ENABLE_DEBUG
      if (check_debug_level (D_MULTI_DEBUG))
	{
	  const char *status = mi ? "[ok]" : "[failed]";

	  dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s",
	       mroute_addr_print (&real, &gc),
	       status);
	}
#endif
    }

  gc_free (&gc);
  ASSERT (!(mi && mi->halt));
  return mi;
}