예제 #1
0
/**
 * g_vfs_ftp_connection_enable_tls:
 * @conn: a connection without an active data connection
 * @server_identity: address of the server used to verify the certificate
 * @cb: callback called if there's a verification error
 * @user_data: user data passed to @cb
 * @cancellable: cancellable to interrupt wait
 * @error: %NULL or location to take a potential error
 *
 * Tries to enable TLS on the given @connection. If setting up TLS fails,
 * %FALSE will be returned and @error will be set. When this function fails,
 * you need to check if the connection is still usable. It might have been
 * closed.
 *
 * Returns: %TRUE on success, %FALSE otherwise.
 **/
gboolean
g_vfs_ftp_connection_enable_tls (GVfsFtpConnection * conn,
                                 GSocketConnectable *server_identity,
                                 CertificateCallback cb,
                                 gpointer            user_data,
                                 GCancellable *      cancellable,
                                 GError **           error)
{
  GIOStream *secure;

  g_return_val_if_fail (conn != NULL, FALSE);
  g_return_val_if_fail (conn->data == NULL, FALSE);
  g_return_val_if_fail (!conn->waiting_for_reply, FALSE);
  g_return_val_if_fail (g_buffered_input_stream_get_available (G_BUFFERED_INPUT_STREAM (conn->commands_in)) == 0, FALSE);

  secure = g_tls_client_connection_new (conn->commands,
                                        server_identity,
                                        error);
  if (secure == NULL)
    return FALSE;

  g_object_unref (conn->commands);
  conn->commands = secure;
  create_input_stream (conn);

  g_signal_connect (secure, "accept-certificate", G_CALLBACK (cb), user_data);

  if (!g_tls_connection_handshake (G_TLS_CONNECTION (secure),
                                   cancellable,
                                   error))
    {
      /* Close here to be sure it won't get used anymore */
      g_io_stream_close (secure, cancellable, NULL);
      return FALSE;
    }

  return TRUE;
}
예제 #2
0
/**
 * g_vfs_ftp_connection_data_connection_enable_tls:
 * @conn: a connection with an active control connection
 * @server_identity: address of the server used to verify the certificate
 * @cb: callback called if there's a verification error
 * @user_data: user data passed to @cb
 * @cancellable: cancellable to interrupt wait
 * @error: %NULL or location to take a potential error
 *
 * Tries to enable TLS on the given @connection's data connection. If setting
 * up TLS fails, %FALSE will be returned and @error will be set.
 *
 * Returns: %TRUE on success, %FALSE otherwise.
 **/
gboolean
g_vfs_ftp_connection_data_connection_enable_tls (GVfsFtpConnection  *conn,
                                                 GSocketConnectable *server_identity,
                                                 CertificateCallback cb,
                                                 gpointer            user_data,
                                                 GCancellable *      cancellable,
                                                 GError **           error)
{
  GIOStream *secure;

  g_return_val_if_fail (conn != NULL, FALSE);
  g_return_val_if_fail (conn->commands != NULL, FALSE);

  secure = g_tls_client_connection_new (conn->data,
                                        server_identity,
                                        error);
  if (secure == NULL)
    return FALSE;

  g_object_unref (conn->data);
  conn->data = secure;

  g_tls_client_connection_copy_session_state (G_TLS_CLIENT_CONNECTION (secure),
                                              G_TLS_CLIENT_CONNECTION (conn->commands));

  g_signal_connect (secure, "accept-certificate", G_CALLBACK (cb), user_data);

  if (!g_tls_connection_handshake (G_TLS_CONNECTION (secure),
                                   cancellable,
                                   error))
    {
      /* Close here to be sure it won't get used anymore */
      g_io_stream_close (secure, cancellable, NULL);
      return FALSE;
    }

  return TRUE;
}
예제 #3
0
static void
on_socket_connect (GObject *object,
                   GAsyncResult *result,
                   gpointer user_data)
{
  CockpitStream *self = user_data;
  GError *error = NULL;

  g_socket_connection_connect_finish (G_SOCKET_CONNECTION (object), result, &error);

  if (!error && !self->priv->closed)
    {
      g_debug ("%s: connected", self->priv->name);

      if (self->priv->options && self->priv->options->tls_client)
        {
          self->priv->io = g_tls_client_connection_new (G_IO_STREAM (object), NULL, &error);
          if (self->priv->io)
            {
              g_debug ("%s: tls handshake", self->priv->name);

              g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (self->priv->io),
                                                            self->priv->options->tls_client_flags);

              if (self->priv->options->tls_cert)
                {
                  g_tls_connection_set_certificate (G_TLS_CONNECTION (self->priv->io),
                                                    self->priv->options->tls_cert);
                }
              if (self->priv->options->tls_database)
                {
                  g_tls_connection_set_database (G_TLS_CONNECTION (self->priv->io),
                                                 self->priv->options->tls_database);
                }

              /* We track data end the same way we do for HTTP */
              g_tls_connection_set_require_close_notify (G_TLS_CONNECTION (self->priv->io), FALSE);
            }
        }
      else
        {
          self->priv->io = g_object_ref (object);
        }
    }

  if (error)
    {
      g_debug ("%s: couldn't connect: %s", self->priv->name, error->message);
      g_clear_error (&self->priv->connect_error);
      self->priv->connect_error = error;

      g_socket_address_enumerator_next_async (self->priv->connecting, NULL,
                                              on_address_next, g_object_ref (self));
    }
  else
    {
      initialize_io (self);
    }

  g_object_unref (object);
  g_object_unref (self);
}
예제 #4
0
static gboolean
make_connection (const char       *argument,
		 GTlsCertificate  *certificate,
		 GCancellable     *cancellable,
		 GSocket         **socket,
		 GSocketAddress  **address,
		 GIOStream       **connection,
		 GInputStream    **istream,
		 GOutputStream   **ostream,
		 GError          **error)
{
  GSocketType socket_type;
  GSocketFamily socket_family;
  GSocketAddressEnumerator *enumerator;
  GSocketConnectable *connectable;
  GSocketAddress *src_address;
  GTlsInteraction *interaction;
  GError *err = NULL;

  if (use_udp)
    socket_type = G_SOCKET_TYPE_DATAGRAM;
  else
    socket_type = G_SOCKET_TYPE_STREAM;

  if (unix_socket)
    socket_family = G_SOCKET_FAMILY_UNIX;
  else
    socket_family = G_SOCKET_FAMILY_IPV4;

  *socket = g_socket_new (socket_family, socket_type, 0, error);
  if (*socket == NULL)
    return FALSE;

  if (read_timeout)
    g_socket_set_timeout (*socket, read_timeout);

  if (unix_socket)
    {
      GSocketAddress *addr;

      addr = socket_address_from_string (argument);
      if (addr == NULL)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Could not parse '%s' as unix socket name", argument);
          return FALSE;
        }
      connectable = G_SOCKET_CONNECTABLE (addr);
    }
  else
    {
      connectable = g_network_address_parse (argument, 7777, error);
      if (connectable == NULL)
        return FALSE;
    }

  enumerator = g_socket_connectable_enumerate (connectable);
  while (TRUE)
    {
      *address = g_socket_address_enumerator_next (enumerator, cancellable, error);
      if (*address == NULL)
        {
          if (error != NULL && *error == NULL)
            g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                                 "No more addresses to try");
          return FALSE;
        }

      if (g_socket_connect (*socket, *address, cancellable, &err))
        break;
      g_message ("Connection to %s failed: %s, trying next", socket_address_to_string (*address), err->message);
      g_clear_error (&err);

      g_object_unref (*address);
    }
  g_object_unref (enumerator);

  g_print ("Connected to %s\n",
           socket_address_to_string (*address));

  src_address = g_socket_get_local_address (*socket, error);
  if (!src_address)
    {
      g_prefix_error (error, "Error getting local address: ");
      return FALSE;
    }

  g_print ("local address: %s\n",
           socket_address_to_string (src_address));
  g_object_unref (src_address);

  if (use_udp)
    {
      *connection = NULL;
      *istream = NULL;
      *ostream = NULL;
    }
  else
    *connection = G_IO_STREAM (g_socket_connection_factory_create_connection (*socket));

  if (tls)
    {
      GIOStream *tls_conn;

      tls_conn = g_tls_client_connection_new (*connection, connectable, error);
      if (!tls_conn)
        {
          g_prefix_error (error, "Could not create TLS connection: ");
          return FALSE;
        }

      g_signal_connect (tls_conn, "accept-certificate",
                        G_CALLBACK (accept_certificate), NULL);

      interaction = g_tls_console_interaction_new ();
      g_tls_connection_set_interaction (G_TLS_CONNECTION (tls_conn), interaction);
      g_object_unref (interaction);

      if (certificate)
        g_tls_connection_set_certificate (G_TLS_CONNECTION (tls_conn), certificate);

      g_object_unref (*connection);
      *connection = G_IO_STREAM (tls_conn);

      if (!g_tls_connection_handshake (G_TLS_CONNECTION (tls_conn),
                                       cancellable, error))
        {
          g_prefix_error (error, "Error during TLS handshake: ");
          return FALSE;
        }
    }
  g_object_unref (connectable);

  if (*connection)
    {
      *istream = g_io_stream_get_input_stream (*connection);
      *ostream = g_io_stream_get_output_stream (*connection);
    }

  return TRUE;
}