Exemplo n.º 1
0
bool
buf_parse (struct buffer *buf, const int delim, char *line, const int size)
{
  bool eol = false;
  int n = 0;
  int c;

  ASSERT (size > 0);

  do
    {
      c = buf_read_u8 (buf);
      if (c < 0)
	eol = true;
      if (c <= 0 || c == delim)
	c = 0;
      if (n >= size)
	break;
      line[n++] = c;
    }
  while (c);

  line[size-1] = '\0';
  return !(eol && !strlen (line));
}
Exemplo n.º 2
0
/*
 * Act on received restart message from server
 */
void
server_pushed_signal(struct context *c, const struct buffer *buffer, const bool restart, const int adv)
{
    if (c->options.pull)
    {
        struct buffer buf = *buffer;
        const char *m = "";
        if (buf_advance(&buf, adv) && buf_read_u8(&buf) == ',' && BLEN(&buf))
        {
            m = BSTR(&buf);
        }

        /* preserve cached passwords? */
        /* advance to next server? */
        {
            bool purge = true;

            if (m[0] == '[')
            {
                int i;
                for (i = 1; m[i] != '\0' && m[i] != ']'; ++i)
                {
                    if (m[i] == 'P')
                    {
                        purge = false;
                    }
                    else if (m[i] == 'N')
                    {
                        /* next server? */
                        c->options.no_advance = false;
                    }
                }
            }
            if (purge)
            {
                ssl_purge_auth(true);
            }
        }

        if (restart)
        {
            msg(D_STREAM_ERRORS, "Connection reset command was pushed by server ('%s')", m);
            c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed connection reset */
            c->sig->signal_text = "server-pushed-connection-reset";
        }
        else
        {
            msg(D_STREAM_ERRORS, "Halt command was pushed by server ('%s')", m);
            c->sig->signal_received = SIGTERM; /* SOFT-SIGTERM -- server-pushed halt */
            c->sig->signal_text = "server-pushed-halt";
        }
#ifdef ENABLE_MANAGEMENT
        if (management)
        {
            management_notify(management, "info", c->sig->signal_text, m);
        }
#endif
    }
}
Exemplo n.º 3
0
static bool
tls_crypt_v2_verify_metadata(const struct tls_wrap_ctx *ctx,
                             const struct tls_options *opt)
{
    bool ret = false;
    struct gc_arena gc = gc_new();
    const char *tmp_file = NULL;
    struct buffer metadata = ctx->tls_crypt_v2_metadata;
    int metadata_type = buf_read_u8(&metadata);
    if (metadata_type < 0)
    {
        msg(M_WARN, "ERROR: no metadata type");
        goto cleanup;
    }

    tmp_file = platform_create_temp_file(opt->tmp_dir, "tls_crypt_v2_metadata_",
                                         &gc);
    if (!tmp_file || !buffer_write_file(tmp_file, &metadata))
    {
        msg(M_WARN, "ERROR: could not write metadata to file");
        goto cleanup;
    }

    char metadata_type_str[4] = { 0 }; /* Max value: 255 */
    openvpn_snprintf(metadata_type_str, sizeof(metadata_type_str),
                     "%i", metadata_type);
    struct env_set *es = env_set_create(NULL);
    setenv_str(es, "script_type", "tls-crypt-v2-verify");
    setenv_str(es, "metadata_type", metadata_type_str);
    setenv_str(es, "metadata_file", tmp_file);

    struct argv argv = argv_new();
    argv_parse_cmd(&argv, opt->tls_crypt_v2_verify_script);
    argv_msg_prefix(D_TLS_DEBUG, &argv, "Executing tls-crypt-v2-verify");

    ret = openvpn_run_script(&argv, es, 0, "--tls-crypt-v2-verify");

    argv_reset(&argv);
    env_set_destroy(es);

    if (!platform_unlink(tmp_file))
    {
        msg(M_WARN, "WARNING: failed to remove temp file '%s", tmp_file);
    }

    if (ret)
    {
        msg(D_HANDSHAKE, "TLS CRYPT V2 VERIFY SCRIPT OK");
    }
    else
    {
        msg(D_HANDSHAKE, "TLS CRYPT V2 VERIFY SCRIPT ERROR");
    }

cleanup:
    gc_free(&gc);
    return ret;
}
Exemplo n.º 4
0
bool
status_read(struct status_output *so, struct buffer *buf)
{
    bool ret = false;

    if (so && so->fd >= 0 && (so->flags & STATUS_OUTPUT_READ))
    {
        ASSERT(buf_defined(&so->read_buf));
        ASSERT(buf_defined(buf));
        while (true)
        {
            const int c = buf_read_u8(&so->read_buf);

            /* read more of file into buffer */
            if (c == -1)
            {
                int len;

                ASSERT(buf_init(&so->read_buf, 0));
                len = read(so->fd, BPTR(&so->read_buf), BCAP(&so->read_buf));
                if (len <= 0)
                {
                    break;
                }

                ASSERT(buf_inc_len(&so->read_buf, len));
                continue;
            }

            ret = true;

            if (c == '\r')
            {
                continue;
            }

            if (c == '\n')
            {
                break;
            }

            buf_write_u8(buf, c);
        }

        buf_null_terminate(buf);
    }

    return ret;
}
Exemplo n.º 5
0
int
buf_substring_len (const struct buffer *buf, int delim)
{
  int i = 0;
  struct buffer tmp = *buf;
  int c;

  while ((c = buf_read_u8 (&tmp)) >= 0)
    {
      ++i;
      if (c == delim)
	return i;
    }
  return -1;
}
Exemplo n.º 6
0
int
process_incoming_push_msg(struct context *c,
                          const struct buffer *buffer,
                          bool honor_received_options,
                          unsigned int permission_mask,
                          unsigned int *option_types_found)
{
    int ret = PUSH_MSG_ERROR;
    struct buffer buf = *buffer;

#if P2MP_SERVER
    if (buf_string_compare_advance(&buf, "PUSH_REQUEST"))
    {
        ret = process_incoming_push_request(c);
    }
    else
#endif

    if (honor_received_options && buf_string_compare_advance(&buf, "PUSH_REPLY"))
    {
        const uint8_t ch = buf_read_u8(&buf);
        if (ch == ',')
        {
            struct buffer buf_orig = buf;
            if (!c->c2.pulled_options_digest_init_done)
            {
                c->c2.pulled_options_state = md_ctx_new();
                md_ctx_init(c->c2.pulled_options_state, md_kt_get("SHA256"));
                c->c2.pulled_options_digest_init_done = true;
            }
            if (!c->c2.did_pre_pull_restore)
            {
                pre_pull_restore(&c->options, &c->c2.gc);
                c->c2.did_pre_pull_restore = true;
            }
            if (apply_push_options(&c->options,
                                   &buf,
                                   permission_mask,
                                   option_types_found,
                                   c->c2.es))
            {
                push_update_digest(c->c2.pulled_options_state, &buf_orig,
                                   &c->options);
                switch (c->options.push_continuation)
                {
                    case 0:
                    case 1:
                        md_ctx_final(c->c2.pulled_options_state, c->c2.pulled_options_digest.digest);
                        md_ctx_cleanup(c->c2.pulled_options_state);
                        md_ctx_free(c->c2.pulled_options_state);
                        c->c2.pulled_options_state = NULL;
                        c->c2.pulled_options_digest_init_done = false;
                        ret = PUSH_MSG_REPLY;
                        break;

                    case 2:
                        ret = PUSH_MSG_CONTINUATION;
                        break;
                }
            }
        }
        else if (ch == '\0')
        {
            ret = PUSH_MSG_REPLY;
        }
        /* show_settings (&c->options); */
    }
    return ret;
}
Exemplo n.º 7
0
int
process_incoming_push_msg (struct context *c,
			   const struct buffer *buffer,
			   bool honor_received_options,
			   unsigned int permission_mask,
			   unsigned int *option_types_found)
{
  int ret = PUSH_MSG_ERROR;
  struct buffer buf = *buffer;

#if P2MP_SERVER
  if (buf_string_compare_advance (&buf, "PUSH_REQUEST"))
    {
      if (tls_authentication_status (c->c2.tls_multi, 0) == TLS_AUTHENTICATION_FAILED || c->c2.context_auth == CAS_FAILED)
	{
	  const char *client_reason = tls_client_reason (c->c2.tls_multi);
	  send_auth_failed (c, client_reason);
	  ret = PUSH_MSG_AUTH_FAILURE;
	}
      else if (!c->c2.push_reply_deferred && c->c2.context_auth == CAS_SUCCEEDED)
	{
	  time_t now;

	  openvpn_time(&now);
	  if (c->c2.sent_push_reply_expiry > now)
	    {
	      ret = PUSH_MSG_ALREADY_REPLIED;
	    }
	  else
	    {
	      if (send_push_reply (c))
		{
		  ret = PUSH_MSG_REQUEST;
		  c->c2.sent_push_reply_expiry = now + 30;
		}
	    }
	}
      else
	{
	  ret = PUSH_MSG_REQUEST_DEFERRED;
	}
    }
  else
#endif

  if (honor_received_options && buf_string_compare_advance (&buf, "PUSH_REPLY"))
    {
      const uint8_t ch = buf_read_u8 (&buf);
      if (ch == ',')
	{
	  struct buffer buf_orig = buf;
	  if (!c->c2.pulled_options_md5_init_done)
	    {
	      md5_state_init (&c->c2.pulled_options_state);
	      c->c2.pulled_options_md5_init_done = true;
	    }
	  if (!c->c2.did_pre_pull_restore)
	    {
	      pre_pull_restore (&c->options);
	      c->c2.did_pre_pull_restore = true;
	    }
	  if (apply_push_options (&c->options,
				  &buf,
				  permission_mask,
				  option_types_found,
				  c->c2.es))
	    switch (c->options.push_continuation)
	      {
	      case 0:
	      case 1:
		md5_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
		md5_state_final (&c->c2.pulled_options_state, &c->c2.pulled_options_digest);
	        c->c2.pulled_options_md5_init_done = false;
		ret = PUSH_MSG_REPLY;
		break;
	      case 2:
		md5_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
		ret = PUSH_MSG_CONTINUATION;
		break;
	      }
	}
      else if (ch == '\0')
	{
	  ret = PUSH_MSG_REPLY;
	}
      /* show_settings (&c->options); */
    }
  return ret;
}
Exemplo n.º 8
0
void
process_received_occ_msg (struct context *c)
{
  ASSERT (buf_advance (&c->c2.buf, OCC_STRING_SIZE));
  switch (buf_read_u8 (&c->c2.buf))
    {
    case OCC_REQUEST:
      dmsg (D_PACKET_CONTENT, "RECEIVED OCC_REQUEST");
      c->c2.occ_op = OCC_REPLY;
      break;

    case OCC_MTU_REQUEST:
      dmsg (D_PACKET_CONTENT, "RECEIVED OCC_MTU_REQUEST");
      c->c2.occ_op = OCC_MTU_REPLY;
      break;

    case OCC_MTU_LOAD_REQUEST:
      dmsg (D_PACKET_CONTENT, "RECEIVED OCC_MTU_LOAD_REQUEST");
      c->c2.occ_mtu_load_size = buf_read_u16 (&c->c2.buf);
      if (c->c2.occ_mtu_load_size >= 0)
	c->c2.occ_op = OCC_MTU_LOAD;
      break;

    case OCC_REPLY:
      dmsg (D_PACKET_CONTENT, "RECEIVED OCC_REPLY");
      if (c->options.occ && !TLS_MODE (c) && c->c2.options_string_remote)
	{
	  if (!options_cmp_equal_safe ((char *) BPTR (&c->c2.buf),
				       c->c2.options_string_remote,
				       c->c2.buf.len))
	    {
	      options_warning_safe ((char *) BPTR (&c->c2.buf),
				    c->c2.options_string_remote,
				    c->c2.buf.len);
	    }
	}
      event_timeout_clear (&c->c2.occ_interval);
      break;

    case OCC_MTU_REPLY:
      dmsg (D_PACKET_CONTENT, "RECEIVED OCC_MTU_REPLY");
      c->c2.max_recv_size_remote = buf_read_u16 (&c->c2.buf);
      c->c2.max_send_size_remote = buf_read_u16 (&c->c2.buf);
      if (c->options.mtu_test
	  && c->c2.max_recv_size_remote > 0
	  && c->c2.max_send_size_remote > 0)
	{
	  msg (M_INFO, "NOTE: Empirical MTU test completed [Tried,Actual] local->remote=[%d,%d] remote->local=[%d,%d]",
	       c->c2.max_send_size_local,
	       c->c2.max_recv_size_remote,
	       c->c2.max_send_size_remote,
	       c->c2.max_recv_size_local);
	  if (!c->options.fragment
	      && c->options.proto == PROTO_UDPv4
	      && c->c2.max_send_size_local > TUN_MTU_MIN
	      && (c->c2.max_recv_size_remote < c->c2.max_send_size_local
		  || c->c2.max_recv_size_local < c->c2.max_send_size_remote))
	    msg (M_INFO, "NOTE: This connection is unable to accomodate a UDP packet size of %d. Consider using --fragment or --mssfix options as a workaround.",
		 c->c2.max_send_size_local);
	}
      event_timeout_clear (&c->c2.occ_mtu_load_test_interval);
      break;

    case OCC_EXIT:
      dmsg (D_PACKET_CONTENT, "RECEIVED OCC_EXIT");
      c->sig->signal_received = SIGTERM;
      c->sig->signal_text = "remote-exit";
      break;
    }
  c->c2.buf.len = 0; /* don't pass packet on */
}