Exemple #1
0
/**
 * Activity on our incoming socket.  Read data from the
 * incoming connection.
 *
 * @param cls
 * @param tc scheduler context
 */
static void
do_udp_read (void *cls,
             const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_NAT_AutoHandle *ah = cls;
  unsigned char reply_buf[1024];
  ssize_t rlen;
  struct sockaddr_in answer;


  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
                                   lsock4)))
  {
    rlen = GNUNET_NETWORK_socket_recv (lsock4, reply_buf, sizeof (reply_buf));

    //Lets handle the packet
    memset(&answer, 0, sizeof(struct sockaddr_in));
    if(ah->phase == AUTO_NAT_PUNCHED)
    {
      //Destroy the connection
      GNUNET_NETWORK_socket_close (lsock4);
      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                  "The external server was able to connect back");
      ah->connected_back = GNUNET_YES;
      next_phase (ah);
    }
    else
    {
      if (GNUNET_OK == GNUNET_NAT_stun_handle_packet (reply_buf, rlen, &answer))
      {
        //Process the answer
        process_stun_reply (&answer, ah);
      }
      else
      {
        next_phase (ah);
      }
    }
  }
  else
  {
    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                "TIMEOUT while waiting for an answer\n");
    if (ah->phase == AUTO_NAT_PUNCHED)
    {
      stop_stun();
    }

    next_phase (ah);
  }



}
Exemple #2
0
/**
 * Determine our external IPv4 address and port using an external STUN server
 *
 * @param ah auto setup context
 */
static void
test_stun (struct GNUNET_NAT_AutoHandle *ah)
{

  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running STUN test\n");

  /* Get port from the configuration */
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_number (ah->cfg,
                                             "transport-udp",
                                             "PORT",
                                             &port))
  {
    port = 2086;
  }

  //Lets create the socket
  lsock4 = bind_v4 ();
  if (NULL == lsock4)
  {
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
    next_phase(ah);
    return;
  }
  else
  {
    //Lets call our function now when it accepts
    ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT,
                                            lsock4, &do_udp_read, ah);

  }


  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "STUN service listens on port %u\n",
              port);
  if (GNUNET_NO == GNUNET_NAT_stun_make_request (stun_server, stun_port,
                                                 lsock4, &request_callback,
                                                 NULL))
  {
    /*An error happened*/
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STUN error, stopping\n");
    stop_stun ();
    next_phase (ah);
  }
}
Exemple #3
0
/**
 * Determine our local IP addresses; detect internal IP & IPv6-support
 *
 * @param ah auto setup context
 */
static void
test_local_ip (struct GNUNET_NAT_AutoHandle *ah)
{
  ah->have_v6 = GNUNET_NO;
  ah->ret = GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO; // reset to success if any of the IFs in below iterator has a valid IP
  GNUNET_OS_network_interfaces_list (&process_if, ah);

  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "DISABLEV6",
					 (GNUNET_YES == ah->have_v6) ? "NO" : "YES");
  next_phase (ah);
}
Exemple #4
0
/**
 * Determine our external IPv4 address.
 *
 * @param ah auto setup context
 */
static void
test_external_ip (struct GNUNET_NAT_AutoHandle *ah)
{
  if (GNUNET_NAT_ERROR_SUCCESS != ah->ret)
    next_phase (ah);

  // FIXME: CPS?
  /* try to detect external IP */
  ah->eh = GNUNET_NAT_mini_get_external_ipv4 (TIMEOUT,
					      &set_external_ipv4, ah);
}
Exemple #5
0
/**
 * Set our external IPv4 address based on the UPnP.
 *
 *
 * @param cls closure with our setup context
 * @param addr the address, NULL on errors
 * @param emsg NULL on success, otherwise an error message
 */
static void
set_external_ipv4 (void *cls,
                   const struct in_addr *addr,
                   enum GNUNET_NAT_StatusCode ret)
{
  struct GNUNET_NAT_AutoHandle *ah = cls;
  char buf[INET_ADDRSTRLEN];

  ah->eh = NULL;
  ah->ret = ret;
  if (GNUNET_NAT_ERROR_SUCCESS != ret)
  {
    next_phase (ah);
    return;
  }
  /* enable 'behind nat' */
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
	      _("Detected external IP `%s'\n"),
	      inet_ntop (AF_INET,
			 addr,
			 buf,
			 sizeof (buf)));
  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "BEHIND_NAT", "YES");

  /* set external IP address */
  if (NULL == inet_ntop (AF_INET, addr, buf, sizeof (buf)))
  {
    GNUNET_break (0);
    /* actually, this should never happen, as the caller already executed just
     * this check, but for consistency (eg: future changes in the caller)
     * we still need to report this error...
     */
    ah->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID;
    next_phase (ah);
    return;
  }
  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "EXTERNAL_ADDRESS",
					 buf);
  ah->upnp_set_external_address = GNUNET_YES;
  next_phase (ah);
}
Exemple #6
0
static void
process_stun_reply(struct sockaddr_in* answer, struct GNUNET_NAT_AutoHandle *ah)
{

  ah->stun_ip = inet_ntoa(answer->sin_addr);
  ah->stun_port = ntohs(answer->sin_port);
  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "External IP is: %s , with port %d\n", ah->stun_ip, ah->stun_port);


  next_phase (ah);

}
Exemple #7
0
/**
 * Test if NAT has been punched
 *
 * @param ah auto setup context
 */
static void
test_nat_punched (struct GNUNET_NAT_AutoHandle *ah)
{

  struct GNUNET_CLIENT_Connection *client;
  struct GNUNET_NAT_TestMessage msg;


  if (ah->stun_ip)
  {
    LOG (GNUNET_ERROR_TYPE_INFO,
         "Asking gnunet-nat-server to connect to `%s'\n",
         ah->stun_ip);


    msg.header.size = htons (sizeof (struct GNUNET_NAT_TestMessage));
    msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAT_TEST);
    msg.dst_ipv4 = inet_addr(ah->stun_ip);
    msg.dport = htons(ah->stun_port);
    msg.data = port;
    msg.is_tcp = htonl ((uint32_t) GNUNET_NO);

    client = GNUNET_CLIENT_connect ("gnunet-nat-server", ah->cfg);
    if (NULL == client)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Failed to connect to `gnunet-nat-server'\n"));
      return;
    }

    GNUNET_break (GNUNET_OK ==
                  GNUNET_CLIENT_transmit_and_get_response (client, &msg.header,
                                                           NAT_SERVER_TIMEOUT,
                                                           GNUNET_YES, NULL,
                                                           NULL));
    if (NULL != ltask4)
    {
      GNUNET_SCHEDULER_cancel (ltask4);
      ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT,
                                              lsock4, &do_udp_read, ah);
    }

  }
  else
  {
    LOG (GNUNET_ERROR_TYPE_INFO,
         "We don't have a STUN IP");
    next_phase(ah);
  }


}
Exemple #8
0
/**
 * Test if UPnPC works.
 *
 * @param ah auto setup context
 */
static void
test_upnpc (struct GNUNET_NAT_AutoHandle *ah)
{

  int have_upnpc;

  if (GNUNET_NAT_ERROR_SUCCESS != ah->ret)
    next_phase (ah);

  // test if upnpc is available
  have_upnpc = (GNUNET_SYSERR !=
		GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL));
  //FIXME: test if upnpc is actually working, that is, if transports start to work once we use UPnP
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
	      (have_upnpc)
	      ? _("upnpc found, enabling its use\n")
	      : _("upnpc not found\n"));
  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_UPNP",
					 (GNUNET_YES == have_upnpc) ? "YES" : "NO");
  next_phase (ah);

}
Exemple #9
0
/**
 * Test if ICMP server is working
 *
 * @param ah auto setup context
 */
static void
test_icmp_server (struct GNUNET_NAT_AutoHandle *ah)
{

  int ext_ip;
  int nated;
  int binary;
  char *tmp;
  char *helper;
  ext_ip = GNUNET_NO;
  nated = GNUNET_NO;
  binary = GNUNET_NO;

  tmp = NULL;
  helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
  if ((GNUNET_OK ==
        GNUNET_CONFIGURATION_get_value_string (ah->cfg, "nat", "EXTERNAL_ADDRESS",
                                               &tmp)) && (0 < strlen (tmp))){
    ext_ip = GNUNET_OK;
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("test_icmp_server not possible, as we have no public IPv4 address\n"));
  }
  else
    goto err;

  if (GNUNET_YES ==
        GNUNET_CONFIGURATION_get_value_yesno (ah->cfg, "nat", "BEHIND_NAT")){
    nated = GNUNET_YES;
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("test_icmp_server not possible, as we are not behind NAT\n"));
  }
  else
    goto err;

  if (GNUNET_YES ==
        GNUNET_OS_check_helper_binary (helper, GNUNET_YES, "-d 127.0.0.1" )){
    binary = GNUNET_OK; // use localhost as source for that one udp-port, ok for testing
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("No working gnunet-helper-nat-server found\n"));
  }
err:
  GNUNET_free_non_null (tmp);
  GNUNET_free (helper);

  if (GNUNET_OK == ext_ip && GNUNET_YES == nated && GNUNET_OK == binary)
    ah->task = GNUNET_SCHEDULER_add_now (&reversal_test, ah);
  else
    next_phase (ah);

}
static gboolean io_cb(GIOChannel *channel, GIOCondition condition, gpointer user_data) {
	TyonXceleratorCalibrationAssistant *assistant = (TyonXceleratorCalibrationAssistant *)user_data;
	TyonXceleratorCalibrationAssistantPrivate *priv = assistant->priv;
	GError *local_error = NULL;
	gint value;
	GIOStatus status;
	gsize length;
	TyonSpecial event;

	if (condition & G_IO_HUP)
		return FALSE;

	status = g_io_channel_read_chars(channel, (gchar *)&event, sizeof(TyonSpecial), &length, &local_error);

	if (status == G_IO_STATUS_AGAIN)
		return TRUE;

	if (status == G_IO_STATUS_ERROR) {
		show_error_summary(assistant, _("Could not read io_channel"));
		g_error_free(local_error);
		return FALSE;
	}

	if (status == G_IO_STATUS_EOF) {
		show_error_summary(assistant, _("Could not read io_channel"));
		return FALSE;
	}

	if (length < sizeof(TyonSpecial) ||
			event.report_id != TYON_REPORT_ID_SPECIAL ||
			event.type != TYON_SPECIAL_TYPE_XCELERATOR)
		return TRUE;

	value = event.action;
	tyon_2d_positional_set(priv->positional, 0.0, (gdouble)(value - 127) / 127.0);

	switch(priv->phase) {
	case PHASE_MID:
		if (in_range(value, priv->last_value, 10)) {
			priv->mid += value;
			++priv->count;
			gtk_progress_bar_set_fraction(priv->progress_bar, 1.0 / valid_count * priv->count);
			if (priv->count == valid_count) {
				priv->mid = priv->mid >> AVERAGE_SHIFT;
				next_phase(assistant);
			}
		} else {
Exemple #11
0
/**
 * Function called by NAT to report the outcome of the nat-test.
 * Clean up and update GUI.
 *
 * @param cls the auto handle
 * @param success currently always #GNUNET_OK
 * @param emsg NULL on success, otherwise an error message
 */
static void
result_callback (void *cls,
                 enum GNUNET_NAT_StatusCode ret)
{
  struct GNUNET_NAT_AutoHandle *ah = cls;

  if (GNUNET_NAT_ERROR_SUCCESS == ret)
    GNUNET_NAT_test_stop (ah->tst);
  ah->tst = NULL;
  ah->ret = ret;
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              GNUNET_NAT_ERROR_SUCCESS == ret
	      ? _("NAT traversal with ICMP Server succeeded.\n")
	      : _("NAT traversal with ICMP Server failed.\n"));
  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_ICMP_SERVER",
					 GNUNET_NAT_ERROR_SUCCESS == ret ? "NO" : "YES");
  next_phase (ah);
}
Exemple #12
0
/**
 * Start auto-configuration routine.  The resolver service should
 * be available when this function is called.
 *
 * @param cfg initial configuration
 * @param cb function to call with autoconfiguration result
 * @param cb_cls closure for @a cb
 * @return handle to cancel operation
 */
struct GNUNET_NAT_AutoHandle *
GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
			     GNUNET_NAT_AutoResultCallback cb,
			     void *cb_cls)
{
  struct GNUNET_NAT_AutoHandle *ah;

  ah = GNUNET_new (struct GNUNET_NAT_AutoHandle);
  ah->fin_cb = cb;
  ah->fin_cb_cls = cb_cls;
  ah->ret = GNUNET_NAT_ERROR_SUCCESS;
  ah->cfg = GNUNET_CONFIGURATION_dup (cfg);
  ah->initial_cfg = GNUNET_CONFIGURATION_dup (cfg);

  /* never use loopback addresses if user wanted autoconfiguration */
  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat",
					 "USE_LOCALADDR",
					 "NO");

  next_phase (ah);
  return ah;
}
Exemple #13
0
/**
 * Test if ICMP client is working
 *
 * @param ah auto setup context
 */
static void
test_icmp_client (struct GNUNET_NAT_AutoHandle *ah)
{


  char *tmp;
  char *helper;

  tmp = NULL;
  helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
  if ((GNUNET_OK ==
        GNUNET_CONFIGURATION_get_value_string (ah->cfg, "nat", "INTERNAL_ADDRESS",
                                               &tmp)) && (0 < strlen (tmp)))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("test_icmp_client not possible, as we have no internal IPv4 address\n"));
  }
  else
    goto err;

  if (GNUNET_YES !=
      GNUNET_CONFIGURATION_get_value_yesno (ah->cfg, "nat", "BEHIND_NAT")){
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("test_icmp_server not possible, as we are not behind NAT\n"));
  }
  else
    goto err;

  if (GNUNET_YES ==
      GNUNET_OS_check_helper_binary (helper, GNUNET_YES, "-d 127.0.0.1 127.0.0.2 42")){
          // none of these parameters are actually used in privilege testing mode
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("No working gnunet-helper-nat-server found\n"));
  }
err:
  GNUNET_free_non_null (tmp);
  GNUNET_free (helper);

  next_phase (ah);

}
Exemple #14
0
/*
 * Note that |extra| points to the correct client/server configuration
 * within |test_ctx|. When configuring the handshake, general mode settings
 * are taken from |test_ctx|, and client/server-specific settings should be
 * taken from |extra|.
 *
 * The configuration code should never reach into |test_ctx->extra| or
 * |test_ctx->resume_extra| directly.
 *
 * (We could refactor test mode settings into a substructure. This would result
 * in cleaner argument passing but would complicate the test configuration
 * parsing.)
 */
static HANDSHAKE_RESULT *do_handshake_internal(
    SSL_CTX *server_ctx, SSL_CTX *server2_ctx, SSL_CTX *client_ctx,
    const SSL_TEST_CTX *test_ctx, const SSL_TEST_EXTRA_CONF *extra,
    SSL_SESSION *session_in, SSL_SESSION **session_out)
{
    PEER server, client;
    BIO *client_to_server, *server_to_client;
    HANDSHAKE_EX_DATA server_ex_data, client_ex_data;
    CTX_DATA client_ctx_data, server_ctx_data, server2_ctx_data;
    HANDSHAKE_RESULT *ret = HANDSHAKE_RESULT_new();
    int client_turn = 1;
    connect_phase_t phase = HANDSHAKE;
    handshake_status_t status = HANDSHAKE_RETRY;
    const unsigned char* tick = NULL;
    size_t tick_len = 0;
    SSL_SESSION* sess = NULL;
    const unsigned char *proto = NULL;
    /* API dictates unsigned int rather than size_t. */
    unsigned int proto_len = 0;

    memset(&server_ctx_data, 0, sizeof(server_ctx_data));
    memset(&server2_ctx_data, 0, sizeof(server2_ctx_data));
    memset(&client_ctx_data, 0, sizeof(client_ctx_data));
    memset(&server, 0, sizeof(server));
    memset(&client, 0, sizeof(client));

    configure_handshake_ctx(server_ctx, server2_ctx, client_ctx, test_ctx, extra,
                            &server_ctx_data, &server2_ctx_data, &client_ctx_data);

    /* Setup SSL and buffers; additional configuration happens below. */
    create_peer(&server, server_ctx);
    create_peer(&client, client_ctx);

    server.bytes_to_write = client.bytes_to_read = test_ctx->app_data_size;
    client.bytes_to_write = server.bytes_to_read = test_ctx->app_data_size;

    configure_handshake_ssl(server.ssl, client.ssl, extra);
    if (session_in != NULL) {
        /* In case we're testing resumption without tickets. */
        TEST_check(SSL_CTX_add_session(server_ctx, session_in));
        TEST_check(SSL_set_session(client.ssl, session_in));
    }

    memset(&server_ex_data, 0, sizeof(server_ex_data));
    memset(&client_ex_data, 0, sizeof(client_ex_data));

    ret->result = SSL_TEST_INTERNAL_ERROR;

    client_to_server = BIO_new(BIO_s_mem());
    server_to_client = BIO_new(BIO_s_mem());

    TEST_check(client_to_server != NULL);
    TEST_check(server_to_client != NULL);

    /* Non-blocking bio. */
    BIO_set_nbio(client_to_server, 1);
    BIO_set_nbio(server_to_client, 1);

    SSL_set_connect_state(client.ssl);
    SSL_set_accept_state(server.ssl);

    /* The bios are now owned by the SSL object. */
    SSL_set_bio(client.ssl, server_to_client, client_to_server);
    TEST_check(BIO_up_ref(server_to_client) > 0);
    TEST_check(BIO_up_ref(client_to_server) > 0);
    SSL_set_bio(server.ssl, client_to_server, server_to_client);

    ex_data_idx = SSL_get_ex_new_index(0, "ex data", NULL, NULL, NULL);
    TEST_check(ex_data_idx >= 0);

    TEST_check(SSL_set_ex_data(server.ssl, ex_data_idx, &server_ex_data) == 1);
    TEST_check(SSL_set_ex_data(client.ssl, ex_data_idx, &client_ex_data) == 1);

    SSL_set_info_callback(server.ssl, &info_cb);
    SSL_set_info_callback(client.ssl, &info_cb);

    client.status = server.status = PEER_RETRY;

    /*
     * Half-duplex handshake loop.
     * Client and server speak to each other synchronously in the same process.
     * We use non-blocking BIOs, so whenever one peer blocks for read, it
     * returns PEER_RETRY to indicate that it's the other peer's turn to write.
     * The handshake succeeds once both peers have succeeded. If one peer
     * errors out, we also let the other peer retry (and presumably fail).
     */
    for(;;) {
        if (client_turn) {
            do_connect_step(&client, phase);
            status = handshake_status(client.status, server.status,
                                      1 /* client went last */);
        } else {
            do_connect_step(&server, phase);
            status = handshake_status(server.status, client.status,
                                      0 /* server went last */);
        }

        switch (status) {
        case HANDSHAKE_SUCCESS:
            phase = next_phase(phase);
            if (phase == CONNECTION_DONE) {
                ret->result = SSL_TEST_SUCCESS;
                goto err;
            } else {
                client.status = server.status = PEER_RETRY;
                /*
                 * For now, client starts each phase. Since each phase is
                 * started separately, we can later control this more
                 * precisely, for example, to test client-initiated and
                 * server-initiated shutdown.
                 */
                client_turn = 1;
                break;
            }
        case CLIENT_ERROR:
            ret->result = SSL_TEST_CLIENT_FAIL;
            goto err;
        case SERVER_ERROR:
            ret->result = SSL_TEST_SERVER_FAIL;
            goto err;
        case INTERNAL_ERROR:
            ret->result = SSL_TEST_INTERNAL_ERROR;
            goto err;
        case HANDSHAKE_RETRY:
            /* Continue. */
            client_turn ^= 1;
            break;
        }
    }
 err:
    ret->server_alert_sent = server_ex_data.alert_sent;
    ret->server_num_fatal_alerts_sent = server_ex_data.num_fatal_alerts_sent;
    ret->server_alert_received = client_ex_data.alert_received;
    ret->client_alert_sent = client_ex_data.alert_sent;
    ret->client_num_fatal_alerts_sent = client_ex_data.num_fatal_alerts_sent;
    ret->client_alert_received = server_ex_data.alert_received;
    ret->server_protocol = SSL_version(server.ssl);
    ret->client_protocol = SSL_version(client.ssl);
    ret->servername = server_ex_data.servername;
    if ((sess = SSL_get0_session(client.ssl)) != NULL)
        SSL_SESSION_get0_ticket(sess, &tick, &tick_len);
    if (tick == NULL || tick_len == 0)
        ret->session_ticket = SSL_TEST_SESSION_TICKET_NO;
    else
        ret->session_ticket = SSL_TEST_SESSION_TICKET_YES;
    ret->session_ticket_do_not_call = server_ex_data.session_ticket_do_not_call;

#ifndef OPENSSL_NO_NEXTPROTONEG
    SSL_get0_next_proto_negotiated(client.ssl, &proto, &proto_len);
    ret->client_npn_negotiated = dup_str(proto, proto_len);

    SSL_get0_next_proto_negotiated(server.ssl, &proto, &proto_len);
    ret->server_npn_negotiated = dup_str(proto, proto_len);
#endif

    SSL_get0_alpn_selected(client.ssl, &proto, &proto_len);
    ret->client_alpn_negotiated = dup_str(proto, proto_len);

    SSL_get0_alpn_selected(server.ssl, &proto, &proto_len);
    ret->server_alpn_negotiated = dup_str(proto, proto_len);

    ret->client_resumed = SSL_session_reused(client.ssl);
    ret->server_resumed = SSL_session_reused(server.ssl);

    if (session_out != NULL)
        *session_out = SSL_get1_session(client.ssl);

    ctx_data_free_data(&server_ctx_data);
    ctx_data_free_data(&server2_ctx_data);
    ctx_data_free_data(&client_ctx_data);

    peer_free_data(&server);
    peer_free_data(&client);
    return ret;
}