static GDBusConnection *
create_connection (GIOStream  *stream,
                   GMainLoop  *main_loop,
                   GError    **error)
{
  GDBusConnection *ret;

  g_assert (G_IS_IO_STREAM (stream));
  g_assert (main_loop != NULL);
  g_assert (error != NULL);

  if ((ret = g_dbus_connection_new_sync (stream, NULL,
                                          G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING,
                                          NULL, NULL, error)))
    {
      g_dbus_connection_set_exit_on_close (ret, FALSE);
      g_signal_connect_swapped (ret, "closed", G_CALLBACK (g_main_loop_quit), main_loop);
    }

  return ret;
}
Exemple #2
0
/* Called in new thread */
static gboolean
on_run (GSocketService    *service,
        GSocketConnection *socket_connection,
        GObject           *source_object,
        gpointer           user_data)
{
  GDBusServer *server = G_DBUS_SERVER (user_data);
  GDBusConnection *connection;
  GDBusConnectionFlags connection_flags;

  if (server->nonce != NULL)
    {
      gchar buf[16];
      gsize bytes_read;

      if (!g_input_stream_read_all (g_io_stream_get_input_stream (G_IO_STREAM (socket_connection)),
                                    buf,
                                    16,
                                    &bytes_read,
                                    NULL,  /* GCancellable */
                                    NULL)) /* GError */
        goto out;

      if (bytes_read != 16)
        goto out;

      if (memcmp (buf, server->nonce, 16) != 0)
        goto out;
    }

  connection_flags =
    G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER |
    G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING;
  if (server->flags & G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS)
    connection_flags |= G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;

  connection = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
                                           server->guid,
                                           connection_flags,
                                           server->authentication_observer,
                                           NULL,  /* GCancellable */
                                           NULL); /* GError */
  if (connection == NULL)
      goto out;

  if (server->flags & G_DBUS_SERVER_FLAGS_RUN_IN_THREAD)
    {
      gboolean claimed;

      claimed = FALSE;
      g_signal_emit (server,
                     _signals[NEW_CONNECTION_SIGNAL],
                     0,
                     connection,
                     &claimed);
      if (claimed)
        g_dbus_connection_start_message_processing (connection);
      g_object_unref (connection);
    }
  else
    {
      GSource *idle_source;
      EmitIdleData *data;

      data = g_new0 (EmitIdleData, 1);
      data->server = g_object_ref (server);
      data->connection = g_object_ref (connection);

      idle_source = g_idle_source_new ();
      g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
      g_source_set_callback (idle_source,
                             emit_new_connection_in_idle,
                             data,
                             (GDestroyNotify) emit_idle_data_free);
      g_source_attach (idle_source, server->main_context_at_construction);
      g_source_unref (idle_source);
    }

 out:
  return TRUE;
}
static GDBusConnection*
get_connection_for_path (gchar *sysroot,
                         gboolean force_peer,
                         GPid *out_peer_pid,
                         GCancellable *cancellable,
                         GError **error)
{
  glnx_unref_object GDBusConnection *connection = NULL;
  glnx_unref_object GSocketConnection *stream = NULL;
  glnx_unref_object GSocket *socket = NULL;
  _cleanup_peer_ GPid peer_pid = 0;

  gchar buffer[16];

  int pair[2];

  const gchar *args[] = {
    "rpm-ostree",
    "start-daemon",
    "--sysroot", sysroot,
    "--dbus-peer", buffer,
    NULL
  };

  /* This is only intended for use by installed tests.
   * Note that it disregards the 'sysroot' and 'force_peer' options
   * and assumes the service activation command has been configured
   * to use the desired system root path. */
  if (g_getenv ("RPMOSTREE_USE_SESSION_BUS") != NULL)
    {
      if (sysroot != NULL)
        g_warning ("RPMOSTREE_USE_SESSION_BUS set, ignoring --sysroot=%s", sysroot);

      /* NB: as opposed to other early returns, this is _also_ a happy path */
      GDBusConnection *ret = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, error);
      if (!ret)
        return glnx_prefix_error_null (error, "Connecting to session bus");
      return ret;
    }

  if (sysroot == NULL)
    sysroot = "/";

  if (g_strcmp0 ("/", sysroot) == 0 && force_peer == FALSE)
    {
      /* NB: as opposed to other early returns, this is _also_ a happy path */
      GDBusConnection *ret = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error);
      if (!ret)
        return glnx_prefix_error_null (error, "Connecting to system bus");
      return ret;
    }

  g_print ("Running in single user mode. Be sure no other users are modifying the system\n");
  if (socketpair (AF_UNIX, SOCK_STREAM, 0, pair) < 0)
    return glnx_null_throw_errno_prefix (error, "couldn't create socket pair");

  g_snprintf (buffer, sizeof (buffer), "%d", pair[1]);

  socket = g_socket_new_from_fd (pair[0], error);
  if (socket == NULL)
    {
      close (pair[0]);
      close (pair[1]);
      return NULL;
    }

  if (!g_spawn_async (NULL, (gchar **)args, NULL,
                      G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD,
                      NULL, NULL, &peer_pid, error))
    {
      close (pair[1]);
      return NULL;
    }

  stream = g_socket_connection_factory_create_connection (socket);
  connection = g_dbus_connection_new_sync (G_IO_STREAM (stream), NULL,
                                           G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
                                           NULL, cancellable, error);
  if (!connection)
    return NULL;

  *out_peer_pid = peer_pid; peer_pid = 0;
  return connection;
}