Пример #1
0
void
process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
{
  if (!c->options.ce.mssfix)
    flags &= ~PIPV4_MSSFIX;
#if PASSTOS_CAPABILITY
  if (!c->options.passtos)
    flags &= ~PIPV4_PASSTOS;
#endif
  if (!c->options.route_gateway_via_dhcp)
    flags &= ~PIPV4_EXTRACT_DHCP_ROUTER;

  if (buf->len > 0)
    {
      /*
       * The --passtos and --mssfix options require
       * us to examine the IPv4 header.
       */
#if PASSTOS_CAPABILITY
      if (flags & (PIPV4_PASSTOS|PIPV4_MSSFIX))
#else
      if (flags & PIPV4_MSSFIX)
#endif
	{
	  struct buffer ipbuf = *buf;
	  if (is_ipv4 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf))
	    {
#if PASSTOS_CAPABILITY
	      /* extract TOS from IP header */
	      if (flags & PIPV4_PASSTOS)
		link_socket_extract_tos (c->c2.link_socket, &ipbuf);
#endif
			  
	      /* possibly alter the TCP MSS */
	      if (flags & PIPV4_MSSFIX)
		mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));

#ifdef ENABLE_CLIENT_NAT
	      /* possibly do NAT on packet */
	      if ((flags & PIPV4_CLIENT_NAT) && c->options.client_nat)
		{
		  const int direction = (flags & PIPV4_OUTGOING) ? CN_INCOMING : CN_OUTGOING;
		  client_nat_transform (c->options.client_nat, &ipbuf, direction);
		}
#endif
	      /* possibly extract a DHCP router message */
	      if (flags & PIPV4_EXTRACT_DHCP_ROUTER)
		{
		  const in_addr_t dhcp_router = dhcp_extract_router_msg (&ipbuf);
		  if (dhcp_router)
		    route_list_add_vpn_gateway (c->c1.route_list, c->c2.es, dhcp_router);
		}
	    }
	}
    }
}
Пример #2
0
void
read_incoming_tun (struct context *c)
{
  /*
   * Setup for read() call on TUN/TAP device.
   */
  /*ASSERT (!c->c2.to_link.len);*/

  perf_push (PERF_READ_IN_TUN);

  c->c2.buf = c->c2.buffers->read_tun_buf;
#ifdef TUN_PASS_BUFFER
  read_tun_buffered (c->c1.tuntap, &c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame));
#else
  ASSERT (buf_init (&c->c2.buf, FRAME_HEADROOM (&c->c2.frame)));
  ASSERT (buf_safe (&c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame)));
  c->c2.buf.len = read_tun (c->c1.tuntap, BPTR (&c->c2.buf), MAX_RW_SIZE_TUN (&c->c2.frame));
#endif

#ifdef PACKET_TRUNCATION_CHECK
  ipv4_packet_size_verify (BPTR (&c->c2.buf),
			   BLEN (&c->c2.buf),
			   TUNNEL_TYPE (c->c1.tuntap),
			   "READ_TUN",
			   &c->c2.n_trunc_tun_read);
#endif

  /* Was TUN/TAP interface stopped? */
  if (tuntap_stop (c->c2.buf.len))
    {
      register_signal (c, SIGTERM, "tun-stop");
      msg (M_INFO, "TUN/TAP interface has been stopped, exiting");
      perf_pop ();
      return;		  
    }

  /* Was TUN/TAP I/O operation aborted? */
  if (tuntap_abort(c->c2.buf.len))
  {
     register_signal(c, SIGHUP, "tun-abort");
     c->persist.restart_sleep_seconds = 10;
     msg(M_INFO, "TUN/TAP I/O operation aborted, restarting");
     perf_pop();
     return;
  }

  /* Check the status return from read() */
  check_status (c->c2.buf.len, "read from TUN/TAP", NULL, c->c1.tuntap);

  perf_pop ();
}
Пример #3
0
void
process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
{
  if (!c->options.mssfix)
    flags &= ~PIPV4_MSSFIX;
#if PASSTOS_CAPABILITY
  if (!c->options.passtos)
    flags &= ~PIPV4_PASSTOS;
#endif
  if (!c->options.route_gateway_via_dhcp || !route_list_default_gateway_needed (c->c1.route_list))
    flags &= ~PIPV4_EXTRACT_DHCP_ROUTER;

  if (buf->len > 0)
    {
      /*
       * The --passtos and --mssfix options require
       * us to examine the IPv4 header.
       */
#if PASSTOS_CAPABILITY
      if (flags & (PIPV4_PASSTOS|PIPV4_MSSFIX))
#else
      if (flags & PIPV4_MSSFIX)
#endif
	{
	  struct buffer ipbuf = *buf;
	  if (is_ipv4 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf))
	    {
#if PASSTOS_CAPABILITY
	      /* extract TOS from IP header */
	      if (flags & PIPV4_PASSTOS)
		link_socket_extract_tos (c->c2.link_socket, &ipbuf);
#endif
			  
	      /* possibly alter the TCP MSS */
	      if (flags & PIPV4_MSSFIX)
		mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));

	      /* possibly extract a DHCP router message */
	      if (flags & PIPV4_EXTRACT_DHCP_ROUTER)
		{
		  const in_addr_t dhcp_router = dhcp_extract_router_msg (&ipbuf);
		  route_list_add_default_gateway (c->c1.route_list, c->c2.es, dhcp_router);
		}
	    }
	}
    }
}
Пример #4
0
void
process_incoming_tun (struct context *c)
{
  struct gc_arena gc = gc_new ();

  perf_push (PERF_PROC_IN_TUN);

  if (c->c2.buf.len > 0)
    c->c2.tun_read_bytes += c->c2.buf.len;

#ifdef LOG_RW
  if (c->c2.log_rw && c->c2.buf.len > 0)
    fprintf (stderr, "r");
#endif

  /* Show packet content */
  dmsg (D_TUN_RW, "TUN READ [%d]", BLEN (&c->c2.buf));

  if (c->c2.buf.len > 0)
    {
      if ((c->options.mode == MODE_POINT_TO_POINT) && (!c->options.allow_recursive_routing))
	drop_if_recursive_routing (c, &c->c2.buf);
      /*
       * The --passtos and --mssfix options require
       * us to examine the IP header (IPv4 or IPv6).
       */
      process_ip_header (c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf);

#ifdef PACKET_TRUNCATION_CHECK
      /* if (c->c2.buf.len > 1) --c->c2.buf.len; */
      ipv4_packet_size_verify (BPTR (&c->c2.buf),
			       BLEN (&c->c2.buf),
			       TUNNEL_TYPE (c->c1.tuntap),
			       "PRE_ENCRYPT",
			       &c->c2.n_trunc_pre_encrypt);
#endif

      encrypt_sign (c, true);
    }
  else
    {
      buf_reset (&c->c2.to_link);
    }
  perf_pop ();
  gc_free (&gc);
}
Пример #5
0
void
process_incoming_link (struct context *c)
{
  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);

  if (c->c2.buf.len > 0)
    {
      c->c2.link_read_bytes += c->c2.buf.len;
      link_read_bytes_global += c->c2.buf.len;
#ifdef ENABLE_MEMSTATS
      if (mmap_stats)
	mmap_stats->link_read_bytes = link_read_bytes_global;
#endif
      c->c2.original_recv_size = c->c2.buf.len;
#ifdef ENABLE_MANAGEMENT
      if (management)
	{
	  management_bytes_in (management, c->c2.buf.len);
#ifdef MANAGEMENT_DEF_AUTH
	  management_bytes_server (management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context);
#endif
	}
#endif
    }
  else
    c->c2.original_recv_size = 0;
  
#ifdef ENABLE_DEBUG
  /* take action to corrupt packet if we are in gremlin test mode */
  if (c->options.gremlin) {
    if (!ask_gremlin (c->options.gremlin))
      c->c2.buf.len = 0;
    corrupt_gremlin (&c->c2.buf, c->options.gremlin);
  }
#endif

  /* log incoming packet */
#ifdef LOG_RW
  if (c->c2.log_rw && c->c2.buf.len > 0)
    fprintf (stderr, "R");
#endif
  msg (D_LINK_RW, "%s READ [%d] from %s: %s",
       proto2ascii (lsi->proto, true),
       BLEN (&c->c2.buf),
       print_link_socket_actual (&c->c2.from, &gc),
       PROTO_DUMP (&c->c2.buf, &gc));

  /*
   * Good, non-zero length packet received.
   * Commence multi-stage processing of packet,
   * such as authenticate, decrypt, decompress.
   * If any stage fails, it sets buf.len to 0 or -1,
   * telling downstream stages to ignore the packet.
   */
  if (c->c2.buf.len > 0)
    {
      if (!link_socket_verify_incoming_addr (&c->c2.buf, lsi, &c->c2.from))
	link_socket_bad_incoming_addr (&c->c2.buf, lsi, &c->c2.from);

#ifdef ENABLE_CRYPTO
#ifdef ENABLE_SSL
      if (c->c2.tls_multi)
	{
	  /*
	   * If tls_pre_decrypt returns true, it means the incoming
	   * packet was a good TLS control channel packet.  If so, TLS code
	   * will deal with the packet and set buf.len to 0 so downstream
	   * stages ignore it.
	   *
	   * If the packet is a data channel packet, tls_pre_decrypt
	   * 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))
	    {
	      interval_action (&c->c2.tmp_int);

	      /* reset packet received timer if TLS packet */
	      if (c->options.ping_rec_timeout)
		event_timeout_reset (&c->c2.ping_rec_interval);
	    }
	}
#if P2MP_SERVER
      /*
       * Drop non-TLS packet if client-connect script/plugin has not
       * yet succeeded.
       */
      if (c->c2.context_auth != CAS_SUCCEEDED)
	c->c2.buf.len = 0;
#endif
#endif /* ENABLE_SSL */

      /* authenticate and decrypt the incoming packet */
      decrypt_status = openvpn_decrypt (&c->c2.buf, c->c2.buffers->decrypt_buf, &c->c2.crypto_options, &c->c2.frame);

      if (!decrypt_status && link_socket_connection_oriented (c->c2.link_socket))
	{
	  /* 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;
	}

#endif /* ENABLE_CRYPTO */

#ifdef ENABLE_FRAGMENT
      if (c->c2.fragment)
	fragment_incoming (c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment);
#endif

#ifdef ENABLE_LZO
      /* decompress the incoming packet */
      if (lzo_defined (&c->c2.lzo_compwork))
	lzo_decompress (&c->c2.buf, c->c2.buffers->lzo_decompress_buf, &c->c2.lzo_compwork, &c->c2.frame);
#endif

#ifdef PACKET_TRUNCATION_CHECK
      /* if (c->c2.buf.len > 1) --c->c2.buf.len; */
      ipv4_packet_size_verify (BPTR (&c->c2.buf),
			       BLEN (&c->c2.buf),
			       TUNNEL_TYPE (c->c1.tuntap),
			       "POST_DECRYPT",
			       &c->c2.n_trunc_post_decrypt);
#endif

      /*
       * Set our "official" outgoing address, since
       * if buf.len is non-zero, we know the packet
       * authenticated.  In TLS mode we do nothing
       * because TLS mode takes care of source address
       * authentication.
       *
       * Also, update the persisted version of our packet-id.
       */
      if (!TLS_MODE (c))
	link_socket_set_outgoing_addr (&c->c2.buf, lsi, &c->c2.from, NULL, c->c2.es);

      /* reset packet received timer */
      if (c->options.ping_rec_timeout && c->c2.buf.len > 0)
	event_timeout_reset (&c->c2.ping_rec_interval);

      /* increment authenticated receive byte count */
      if (c->c2.buf.len > 0)
	{
	  c->c2.link_read_bytes_auth += c->c2.buf.len;
	  c->c2.max_recv_size_local = max_int (c->c2.original_recv_size, c->c2.max_recv_size_local);
	}

      /* Did we just receive an openvpn ping packet? */
      if (is_ping_msg (&c->c2.buf))
	{
	  dmsg (D_PING, "RECEIVED PING PACKET");
	  c->c2.buf.len = 0; /* drop packet */
	}

#ifdef ENABLE_OCC
      /* Did we just receive an OCC packet? */
      if (is_occ_msg (&c->c2.buf))
	process_received_occ_msg (c);
#endif

      buffer_turnover (orig_buf, &c->c2.to_tun, &c->c2.buf, &c->c2.buffers->read_link_buf);

      /* to_tun defined + unopened tuntap can cause deadlock */
      if (!tuntap_defined (c->c1.tuntap))
	c->c2.to_tun.len = 0;
    }
  else
    {
      buf_reset (&c->c2.to_tun);
    }
 done:
  perf_pop ();
  gc_free (&gc);
}
Пример #6
0
void
process_outgoing_tun (struct context *c)
{
  struct gc_arena gc = gc_new ();

  /*
   * Set up for write() call to TUN/TAP
   * device.
   */
  if (c->c2.to_tun.len <= 0)
    return;

  perf_push (PERF_PROC_OUT_TUN);

  /*
   * The --mssfix option requires
   * us to examine the IPv4 header.
   */
  process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun);

  if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame))
    {
      /*
       * Write to TUN/TAP device.
       */
      int size;

#ifdef LOG_RW
      if (c->c2.log_rw)
	fprintf (stderr, "w");
#endif
      dmsg (D_TUN_RW, "TUN WRITE [%d]", BLEN (&c->c2.to_tun));

#ifdef PACKET_TRUNCATION_CHECK
      ipv4_packet_size_verify (BPTR (&c->c2.to_tun),
			       BLEN (&c->c2.to_tun),
			       TUNNEL_TYPE (c->c1.tuntap),
			       "WRITE_TUN",
			       &c->c2.n_trunc_tun_write);
#endif

#ifdef TUN_PASS_BUFFER
      size = write_tun_buffered (c->c1.tuntap, &c->c2.to_tun);
#else
      size = write_tun (c->c1.tuntap, BPTR (&c->c2.to_tun), BLEN (&c->c2.to_tun));
#endif

      if (size > 0)
	c->c2.tun_write_bytes += size;
      check_status (size, "write to TUN/TAP", NULL, c->c1.tuntap);

      /* check written packet size */
      if (size > 0)
	{
	  /* Did we write a different size packet than we intended? */
	  if (size != BLEN (&c->c2.to_tun))
	    msg (D_LINK_ERRORS,
		 "TUN/TAP packet was destructively fragmented on write to %s (tried=%d,actual=%d)",
		 c->c1.tuntap->actual_name,
		 BLEN (&c->c2.to_tun),
		 size);

	  /* indicate activity regarding --inactive parameter */
	  register_activity (c, size);
	}
    }
  else
    {
      /*
       * This should never happen, probably indicates some kind
       * of MTU mismatch.
       */
      msg (D_LINK_ERRORS, "tun packet too large on write (tried=%d,max=%d)",
	   c->c2.to_tun.len,
	   MAX_RW_SIZE_TUN (&c->c2.frame));
    }

  buf_reset (&c->c2.to_tun);

  perf_pop ();
  gc_free (&gc);
}
Пример #7
0
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);
#endif

#ifdef USE_COMP
      /* decompress the incoming packet */
      if (c->c2.comp_context)
	(*c->c2.comp_context->alg.decompress)(&c->c2.buf, c->c2.buffers->decompress_buf, c->c2.comp_context, &c->c2.frame);
#endif

#ifdef PACKET_TRUNCATION_CHECK
      /* if (c->c2.buf.len > 1) --c->c2.buf.len; */
      ipv4_packet_size_verify (BPTR (&c->c2.buf),
			       BLEN (&c->c2.buf),
			       TUNNEL_TYPE (c->c1.tuntap),
			       "POST_DECRYPT",
			       &c->c2.n_trunc_post_decrypt);
#endif

      /*
       * Set our "official" outgoing address, since
       * if buf.len is non-zero, we know the packet
       * authenticated.  In TLS mode we do nothing
       * because TLS mode takes care of source address
       * authentication.
       *
       * Also, update the persisted version of our packet-id.
       */
      if (!TLS_MODE (c))
	link_socket_set_outgoing_addr (&c->c2.buf, lsi, &c->c2.from, NULL, c->c2.es);

      /* reset packet received timer */
      if (c->options.ping_rec_timeout && c->c2.buf.len > 0)
	event_timeout_reset (&c->c2.ping_rec_interval);

      /* increment authenticated receive byte count */
      if (c->c2.buf.len > 0)
	{
	  c->c2.link_read_bytes_auth += c->c2.buf.len;
	  c->c2.max_recv_size_local = max_int (c->c2.original_recv_size, c->c2.max_recv_size_local);
	}

      /* Did we just receive an openvpn ping packet? */
      if (is_ping_msg (&c->c2.buf))
	{
	  dmsg (D_PING, "RECEIVED PING PACKET");
	  c->c2.buf.len = 0; /* drop packet */
	}

#ifdef ENABLE_OCC
      /* Did we just receive an OCC packet? */
      if (is_occ_msg (&c->c2.buf))
	process_received_occ_msg (c);
#endif

      buffer_turnover (orig_buf, &c->c2.to_tun, &c->c2.buf, &c->c2.buffers->read_link_buf);

      /* to_tun defined + unopened tuntap can cause deadlock */
      if (!tuntap_defined (c->c1.tuntap))
	c->c2.to_tun.len = 0;
    }
  else
    {
      buf_reset (&c->c2.to_tun);
    }
}
Пример #8
0
/**
 * Drops UDP packets which OS decided to route via tun.
 *
 * On Windows and OS X when netwotk adapter is disabled or
 * disconnected, platform starts to use tun as external interface.
 * When packet is sent to tun, it comes to openvpn, encapsulated
 * and sent to routing table, which sends it again to tun.
 */
static void
drop_if_recursive_routing (struct context *c, struct buffer *buf)
{
  bool drop = false;
  struct openvpn_sockaddr tun_sa;
  int ip_hdr_offset = 0;

  if (c->c2.to_link_addr == NULL) /* no remote addr known */
    return;

  tun_sa = c->c2.to_link_addr->dest;

  int proto_ver = get_tun_ip_ver (TUNNEL_TYPE (c->c1.tuntap), &c->c2.buf, &ip_hdr_offset);

  if (proto_ver == 4)
    {
      const struct openvpn_iphdr *pip;

      /* make sure we got whole IP header */
      if (BLEN (buf) < ((int) sizeof (struct openvpn_iphdr) + ip_hdr_offset))
	return;

      /* skip ipv4 packets for ipv6 tun */
      if (tun_sa.addr.sa.sa_family != AF_INET)
	return;

      pip = (struct openvpn_iphdr *) (BPTR (buf) + ip_hdr_offset);

      /* drop packets with same dest addr as gateway */
      if (tun_sa.addr.in4.sin_addr.s_addr == pip->daddr)
	drop = true;
    }
  else if (proto_ver == 6)
    {
      const struct openvpn_ipv6hdr *pip6;

      /* make sure we got whole IPv6 header */
      if (BLEN (buf) < ((int) sizeof (struct openvpn_ipv6hdr) + ip_hdr_offset))
	return;

      /* skip ipv6 packets for ipv4 tun */
      if (tun_sa.addr.sa.sa_family != AF_INET6)
	return;

      /* drop packets with same dest addr as gateway */
      pip6 = (struct openvpn_ipv6hdr *) (BPTR (buf) + ip_hdr_offset);
      if (IN6_ARE_ADDR_EQUAL(&tun_sa.addr.in6.sin6_addr, &pip6->daddr))
	drop = true;
    }

  if (drop)
    {
      struct gc_arena gc = gc_new ();

      c->c2.buf.len = 0;

      msg(D_LOW, "Recursive routing detected, drop tun packet to %s",
		print_link_socket_actual(c->c2.to_link_addr, &gc));
      gc_free (&gc);
    }
}