Esempio n. 1
0
File: auth.c Progetto: finid/cockpit
gboolean
auth_check_uid_role (GDBusMethodInvocation *invocation,
                     uid_t uid,
                     const gchar *role)
{
  int err = 0;
  gs_free struct passwd *pw = NULL;
  gs_free struct group *wheel_gr = NULL;
  gs_free struct group *role_gr = NULL;
  gs_free gid_t *gids = NULL;

  if (uid == 0)
    return TRUE;

  pw = getpwuid_a (uid, &err);
  if (pw == NULL)
    goto error;

  wheel_gr = getgrnam_a ("wheel", NULL);
  role_gr = role ? getgrnam_a (role, NULL) : NULL;

  int n_groups;
  gids = getgrouplist_a (pw->pw_name, pw->pw_gid, &n_groups, &err);
  if (gids == NULL)
    goto error;

  for (int i = 0; i < n_groups; i++)
    if ((wheel_gr && gids[i] == wheel_gr->gr_gid)
        || (role_gr && gids[i] == role_gr->gr_gid))
      return TRUE;

error:
  if (err)
    g_dbus_method_invocation_return_error (invocation,
                                           COCKPIT_ERROR, COCKPIT_ERROR_FAILED,
                                           "%s", strerror(err));
  else
    g_dbus_method_invocation_return_error (invocation,
                                           G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED,
                                           "Method %s.%s needs role '%s'",
                                           g_dbus_method_invocation_get_interface_name (invocation),
                                           g_dbus_method_invocation_get_method_name (invocation),
                                           role ? role : "wheel");
  return FALSE;
}
Esempio n. 2
0
File: auth.c Progetto: finid/cockpit
gboolean
auth_uid_is_wheel (uid_t uid)
{
  gs_free struct passwd *pw = getpwuid_a (uid, NULL);
  if (pw == NULL)
    return FALSE;

  gs_free struct group *gr = getgrnam_a ("wheel", NULL);
  if (gr == NULL)
    return FALSE;

  int n_groups;
  gs_free gid_t *gids = getgrouplist_a (pw->pw_name, pw->pw_gid, &n_groups, NULL);
  if (gids == NULL)
    return FALSE;

  for (int i = 0; i < n_groups; i++)
    if (gids[i] == gr->gr_gid)
      return TRUE;

  return FALSE;
}
Esempio n. 3
0
static int
run_bridge (const gchar *interactive,
            gboolean privileged_slave)
{
  CockpitTransport *transport;
  gboolean terminated = FALSE;
  gboolean interupted = FALSE;
  gboolean closed = FALSE;
  CockpitPortal *super = NULL;
  CockpitPortal *pcp = NULL;
  gpointer polkit_agent = NULL;
  const gchar *directory;
  struct passwd *pwd;
  GPid daemon_pid = 0;
  GPid agent_pid = 0;
  guint sig_term;
  guint sig_int;
  int outfd;
  uid_t uid;

  cockpit_set_journal_logging (G_LOG_DOMAIN, !isatty (2));

  /*
   * The bridge always runs from within $XDG_RUNTIME_DIR
   * This makes it easy to create user sockets and/or files.
   */
  if (!privileged_slave)
    {
      directory = g_get_user_runtime_dir ();
      if (g_mkdir_with_parents (directory, 0700) < 0)
        g_warning ("couldn't create runtime dir: %s: %s", directory, g_strerror (errno));
      else if (g_chdir (directory) < 0)
        g_warning ("couldn't change to runtime dir: %s: %s", directory, g_strerror (errno));
    }

  /* Always set environment variables early */
  uid = geteuid();
  pwd = getpwuid_a (uid);
  if (pwd == NULL)
    {
      g_message ("couldn't get user info: %s", g_strerror (errno));
    }
  else
    {
      g_setenv ("USER", pwd->pw_name, TRUE);
      g_setenv ("HOME", pwd->pw_dir, TRUE);
      g_setenv ("SHELL", pwd->pw_shell, TRUE);
    }

  /* Reset the umask, typically this is done in .bashrc for a login shell */
  umask (022);

  /*
   * This process talks on stdin/stdout. However lots of stuff wants to write
   * to stdout, such as g_debug, and uses fd 1 to do that. Reroute fd 1 so that
   * it goes to stderr, and use another fd for stdout.
   */

  outfd = dup (1);
  if (outfd < 0 || dup2 (2, 1) < 1)
    {
      g_warning ("bridge couldn't redirect stdout to stderr");
      outfd = 1;
    }

  sig_term = g_unix_signal_add (SIGTERM, on_signal_done, &terminated);
  sig_int = g_unix_signal_add (SIGINT, on_signal_done, &interupted);

  g_type_init ();

  /* Start daemons if necessary */
  if (!interactive && !privileged_slave)
    {
      if (!have_env ("DBUS_SESSION_BUS_ADDRESS"))
        daemon_pid = start_dbus_daemon ();
      if (!have_env ("SSH_AUTH_SOCK"))
        agent_pid = start_ssh_agent ();
    }

  packages = cockpit_packages_new ();
  cockpit_dbus_internal_startup (interactive != NULL);

  if (interactive)
    {
      /* Allow skipping the init message when interactive */
      init_received = TRUE;

      transport = cockpit_interact_transport_new (0, outfd, interactive);
    }
  else
    {
      transport = cockpit_pipe_transport_new_fds ("stdio", 0, outfd);
    }

  if (uid != 0)
    {
      if (!interactive)
        polkit_agent = cockpit_polkit_agent_register (transport, NULL);
      super = cockpit_portal_new_superuser (transport);
    }

  g_resources_register (cockpitassets_get_resource ());
  cockpit_web_failure_resource = "/org/cockpit-project/Cockpit/fail.html";

  pcp = cockpit_portal_new_pcp (transport);

  cockpit_dbus_time_startup ();
  cockpit_dbus_user_startup (pwd);
  cockpit_dbus_setup_startup ();

  g_free (pwd);
  pwd = NULL;

  g_signal_connect (transport, "control", G_CALLBACK (on_transport_control), NULL);
  g_signal_connect (transport, "closed", G_CALLBACK (on_closed_set_flag), &closed);
  send_init_command (transport);

  /* Owns the channels */
  channels = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);

  while (!terminated && !closed && !interupted)
    g_main_context_iteration (NULL, TRUE);

  if (polkit_agent)
    cockpit_polkit_agent_unregister (polkit_agent);
  if (super)
    g_object_unref (super);

  g_object_unref (pcp);
  g_object_unref (transport);
  g_hash_table_destroy (channels);

  cockpit_dbus_internal_cleanup ();
  cockpit_packages_free (packages);
  packages = NULL;

  if (daemon_pid)
    kill (daemon_pid, SIGTERM);
  if (agent_pid)
    kill (agent_pid, SIGTERM);

  g_source_remove (sig_term);
  g_source_remove (sig_int);

  /* So the caller gets the right signal */
  if (terminated)
    raise (SIGTERM);

  return 0;
}