From 0671c7073f9910826d9ee67f61af68b3cbd72c1d Mon Sep 17 00:00:00 2001 From: Eric Koegel Date: Fri, 8 Aug 2014 21:26:48 +0300 Subject: [PATCH] Use pkexec for pm-helper (Bug 10943) Switch to using pkexec instead of the sudo helper. This allows users to use things such as fingerprint readers and other auth methods to verify credentials. --- common/xfpm-power-common.h | 2 + src/Makefile.am | 33 +-- src/org.xfce.power.policy.in2 | 15 ++ src/xfpm-pm-helper.c | 92 +++++--- src/xfpm-power.c | 92 +------- src/xfpm-suspend.c | 505 +++--------------------------------------- src/xfpm-suspend.h | 50 +---- 7 files changed, 145 insertions(+), 644 deletions(-) diff --git a/common/xfpm-power-common.h b/common/xfpm-power-common.h index 63db7ad..3b507be 100644 --- a/common/xfpm-power-common.h +++ b/common/xfpm-power-common.h @@ -39,6 +39,8 @@ #define POLKIT_AUTH_SUSPEND_LOGIND "org.freedesktop.login1.suspend" #define POLKIT_AUTH_HIBERNATE_LOGIND "org.freedesktop.login1.hibernate" +#define POLKIT_AUTH_SUSPEND_XFPM "org.xfce.power.xfpm-pm-helper" +#define POLKIT_AUTH_HIBERNATE_XFPM "org.xfce.power.xfpm-pm-helper" const gchar *xfpm_power_translate_device_type (guint type); diff --git a/src/Makefile.am b/src/Makefile.am index c758a03..6ac0b06 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,4 @@ -bin_PROGRAMS = xfce4-power-manager \ - xfce4-pm-helper +bin_PROGRAMS = xfce4-power-manager xfce4_power_manager_SOURCES = \ $(BUILT_SOURCES) \ @@ -45,7 +44,8 @@ xfce4_power_manager_CFLAGS = \ -I$(top_srcdir)/libdbus \ -DLOCALEDIR=\"$(localedir)\" \ -DG_LOG_DOMAIN=\"xfce4-power-manager\" \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DSBINDIR=\"$(sbindir)\" \ -DUPOWER_ENABLE_DEPRECATED \ -DXFPM_SUSPEND_HELPER_CMD=\"$(prefix)/bin/xfce4-pm-helper\" \ $(GOBJECT_CFLAGS) \ @@ -77,19 +77,10 @@ xfce4_power_manager_LDADD = \ $(XRANDR_LIBS) \ $(DPMS_LIBS) -xfce4_pm_helper_SOURCES = \ - xfpm-pm-helper.c - -xfce4_pm_helper_CFLAGS = \ - -I$(top_srcdir) \ - $(LIBXFCE4UTIL_CFLAGS) - -xfce4_pm_helper_LDFLAGS = \ - $(LIBXFCE4UTIL_LIBS) - if ENABLE_POLKIT -sbin_PROGRAMS = xfpm-power-backlight-helper +sbin_PROGRAMS = xfpm-power-backlight-helper \ + xfce4-pm-helper xfpm_power_backlight_helper_SOURCES = \ xfpm-backlight-helper.c @@ -103,6 +94,20 @@ xfpm_power_backlight_helper_CFLAGS = \ $(PLATFORM_CPPFLAGS) \ $(PLATFORM_CFLAGS) +xfce4_pm_helper_SOURCES = \ + xfpm-pm-helper.c + +xfce4_pm_helper_CFLAGS = \ + -I$(top_srcdir) \ + $(GLIB_CFLAGS) \ + $(PLATFORM_CPPFLAGS) \ + $(PLATFORM_CFLAGS) \ + $(LIBXFCE4UTIL_CFLAGS) + +xfce4_pm_helper_LDFLAGS = \ + $(LIBXFCE4UTIL_LIBS) \ + $(GLIB_LIBS) + polkit_policydir = $(datadir)/polkit-1/actions polkit_policy_DATA = \ org.xfce.power.policy diff --git a/src/org.xfce.power.policy.in2 b/src/org.xfce.power.policy.in2 index 5a05964..350173f 100644 --- a/src/org.xfce.power.policy.in2 +++ b/src/org.xfce.power.policy.in2 @@ -28,5 +28,20 @@ @sbindir@/xfpm-power-backlight-helper + + + <_description>Suspend or hibernate the system + <_message>Authentication is required to place the system in suspend or hibernate mode + + auth_admin + auth_admin + auth_admin_keep + + @sbindir@/xfpm-pm-helper + + diff --git a/src/xfpm-pm-helper.c b/src/xfpm-pm-helper.c index bbef9a1..6802094 100644 --- a/src/xfpm-pm-helper.c +++ b/src/xfpm-pm-helper.c @@ -51,6 +51,12 @@ #include /* XXX */ +#define EXIT_CODE_SUCCESS 0 +#define EXIT_CODE_FAILED 1 +#define EXIT_CODE_ARGUMENTS_INVALID 3 +#define EXIT_CODE_INVALID_USER 4 + + #ifdef UP_BACKEND_SUSPEND_COMMAND #undef UP_BACKEND_SUSPEND_COMMAND #endif @@ -60,7 +66,7 @@ #ifdef BACKEND_TYPE_FREEBSD -#define UP_BACKEND_SUSPEND_COMMAND "/usr/sbin/zzz" +#define UP_BACKEND_SUSPEND_COMMAND "/usr/sbin/acpiconf -s 3" #define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/acpiconf -s 4" #endif #ifdef BACKEND_TYPE_LINUX @@ -69,7 +75,7 @@ #endif #ifdef BACKEND_TYPE_OPENBSD #define UP_BACKEND_SUSPEND_COMMAND "/usr/sbin/zzz" -#define UP_BACKEND_HIBERNATE_COMMAND "/dev/null" +#define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/ZZZ" #endif @@ -125,34 +131,66 @@ run (const gchar *command) int main (int argc, char **argv) { - gboolean succeed = FALSE; - char action[1024]; - - /* display banner */ - fprintf (stdout, "XFPM_SUDO_DONE "); - fflush (stdout); - - if (fgets (action, 1024, stdin) == NULL) - { - fprintf (stdout, "FAILED\n"); - return EXIT_FAILURE; - } - - if (strncasecmp (action, "SUSPEND", 7) == 0) + GOptionContext *context; + gint uid; + gint euid; + const gchar *pkexec_uid_str; + gboolean suspend = FALSE; + gboolean hibernate = FALSE; + + const GOptionEntry options[] = { + { "suspend", '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &suspend, "Suspend the system", NULL }, + { "hibernate", '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &hibernate, "Hibernate the system", NULL }, + { NULL } + }; + + context = g_option_context_new (NULL); + g_option_context_set_summary (context, "XFCE Power Management Helper"); + g_option_context_add_main_entries (context, options, NULL); + g_option_context_parse (context, &argc, &argv, NULL); + g_option_context_free (context); + + /* no input */ + if (!suspend && !hibernate) { + puts ("No valid option was specified"); + return EXIT_CODE_ARGUMENTS_INVALID; + } + + /* get calling process */ + uid = getuid (); + euid = geteuid (); + if (uid != 0 || euid != 0) { + puts ("This program can only be used by the root user"); + return EXIT_CODE_ARGUMENTS_INVALID; + } + + /* check we're not being spoofed */ + pkexec_uid_str = g_getenv ("PKEXEC_UID"); + if (pkexec_uid_str == NULL) { + puts ("This program must only be run through pkexec"); + return EXIT_CODE_INVALID_USER; + } + + /* run the command */ + if(suspend) + { + if (run (UP_BACKEND_SUSPEND_COMMAND)) { - succeed = run (UP_BACKEND_SUSPEND_COMMAND); + return EXIT_CODE_SUCCESS; + } else { + return EXIT_CODE_FAILED; } - else if (strncasecmp (action, "HIBERNATE", 9) == 0) - { - succeed = run (UP_BACKEND_HIBERNATE_COMMAND); - } - - if (succeed) + } + else if (hibernate) + { + if(run (UP_BACKEND_HIBERNATE_COMMAND)) { - fprintf (stdout, "SUCCEED\n"); - return EXIT_SUCCESS; + return EXIT_CODE_SUCCESS; + } else { + return EXIT_CODE_FAILED; } + } - fprintf (stdout, "FAILED\n"); - return EXIT_FAILURE; + /* how did we get here? */ + return EXIT_CODE_FAILED; } diff --git a/src/xfpm-power.c b/src/xfpm-power.c index df44cf5..2688715 100644 --- a/src/xfpm-power.c +++ b/src/xfpm-power.c @@ -84,9 +84,6 @@ static void xfpm_update_blank_time (XfpmPower *power); static void xfpm_power_dbus_class_init (XfpmPowerClass * klass); static void xfpm_power_dbus_init (XfpmPower *power); -#if UP_CHECK_VERSION(0, 99, 0) -static gboolean xfpm_power_prompt_password (XfpmPower *power); -#endif #define XFPM_POWER_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), XFPM_TYPE_POWER, XfpmPowerPrivate)) @@ -123,8 +120,6 @@ struct XfpmPowerPrivate gboolean auth_suspend; gboolean auth_hibernate; - XfpmSuspend *suspend; - /* Properties */ gboolean on_low_battery; gboolean lid_is_present; @@ -186,8 +181,13 @@ xfpm_power_check_polkit_auth (XfpmPower *power) } else { +#if !UP_CHECK_VERSION(0, 99, 0) suspend = POLKIT_AUTH_SUSPEND_UPOWER; hibernate = POLKIT_AUTH_HIBERNATE_UPOWER; +#else + suspend = POLKIT_AUTH_SUSPEND_XFPM; + hibernate = POLKIT_AUTH_HIBERNATE_XFPM; +#endif } power->priv->auth_suspend = xfpm_polkit_check_auth (power->priv->polkit, suspend); @@ -338,22 +338,6 @@ xfpm_power_sleep (XfpmPower *power, const gchar *sleep_time, gboolean force) return; } -/* Upower dropped support for doing anything power related */ -#if UP_CHECK_VERSION(0, 99, 0) - if ( !LOGIND_RUNNING () ) - { - /* See if we require a password for sudo to call suspend */ - if ( xfpm_suspend_password_required (power->priv->suspend) ) - { - if ( !xfpm_power_prompt_password (power) ) - { - xfpm_power_report_error (power, _("Incorrect password entered"), "dialog-error"); - return; - } - } - } -#endif - g_signal_emit (G_OBJECT (power), signals [SLEEPING], 0); /* Get the current brightness level so we can use it after we suspend */ brightness = xfpm_brightness_new(); @@ -419,13 +403,11 @@ xfpm_power_sleep (XfpmPower *power, const gchar *sleep_time, gboolean force) #else if (!g_strcmp0 (sleep_time, "Hibernate")) { - if (xfpm_suspend_sudo_get_state (power->priv->suspend) == SUDO_AVAILABLE) - xfpm_suspend_sudo_try_action (power->priv->suspend, XFPM_HIBERNATE, &error); + xfpm_suspend_try_action (XFPM_HIBERNATE); } else { - if (xfpm_suspend_sudo_get_state (power->priv->suspend) == SUDO_AVAILABLE) - xfpm_suspend_sudo_try_action (power->priv->suspend, XFPM_SUSPEND, &error); + xfpm_suspend_try_action (XFPM_SUSPEND); } #endif } @@ -1132,7 +1114,6 @@ xfpm_power_init (XfpmPower *power) power->priv->presentation_mode = FALSE; power->priv->on_ac_blank = 15; power->priv->on_battery_blank = 10; - power->priv->suspend = xfpm_suspend_get (); power->priv->inhibit = xfpm_inhibit_new (); power->priv->notify = xfpm_notify_new (); @@ -1420,65 +1401,6 @@ xfpm_power_is_in_presentation_mode (XfpmPower *power) return power->priv->presentation_mode; } -/* ifdef this out to prevent an unused function warning */ -#if UP_CHECK_VERSION(0, 99, 0) -static gboolean -xfpm_power_prompt_password (XfpmPower *power) -{ - GtkWidget *dialog = gtk_message_dialog_new (NULL, - GTK_DIALOG_MODAL, - GTK_MESSAGE_OTHER, - GTK_BUTTONS_OK_CANCEL, - _("The requested operation requires elevated privileges.\n" - "Please enter your password.")); - GtkWidget *content_area = gtk_dialog_get_content_area (GTK_DIALOG(dialog)); - GtkWidget *password_entry = gtk_entry_new (); - GtkWidget *password_label, *hbox; - gint result; - XfpmPassState state = PASSWORD_FAILED; - - /* Set the dialog's title */ - gtk_window_set_title (GTK_WINDOW(dialog), _("xfce4-power-manager")); - - /* setup password label */ - password_label = gtk_label_new (_("Password:")); - - /* Setup the password entry */ - gtk_entry_set_visibility (GTK_ENTRY (password_entry), FALSE); - gtk_entry_set_max_length (GTK_ENTRY (password_entry), 1024); - gtk_entry_set_activates_default (GTK_ENTRY (password_entry), TRUE); - - /* pack the password label and entry into an hbox */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (hbox), password_label, FALSE, FALSE, 4); - gtk_box_pack_end (GTK_BOX (hbox), password_entry, TRUE, TRUE, 4); - - /* Add it to the dialog */ - gtk_box_pack_end (GTK_BOX (content_area), hbox, TRUE, TRUE, 8); - - /* show it */ - gtk_widget_show (password_entry); - gtk_widget_show (password_label); - gtk_widget_show (hbox); - - /* make enter default to ok */ - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); - - /* Run the password prompt */ - result = gtk_dialog_run (GTK_DIALOG(dialog)); - - if (result == GTK_RESPONSE_OK) - { - state = xfpm_suspend_sudo_send_password (power->priv->suspend, gtk_entry_get_text (GTK_ENTRY (password_entry))); - XFPM_DEBUG ("password state: %s", state == PASSWORD_FAILED ? "PASSWORD_FAILED" : "PASSWORD_SUCCEED"); - } - - gtk_widget_destroy (dialog); - - return state == PASSWORD_FAILED ? FALSE : TRUE; -} -#endif - /* * diff --git a/src/xfpm-suspend.c b/src/xfpm-suspend.c index 63f4bf6..091ab9e 100644 --- a/src/xfpm-suspend.c +++ b/src/xfpm-suspend.c @@ -48,474 +48,6 @@ #include "xfpm-suspend.h" -static void xfpm_suspend_sudo_free (XfpmSuspend *suspend); - -static void xfpm_suspend_sudo_childwatch (GPid pid, - gint status, - gpointer data); - -static gboolean xfpm_suspend_sudo_init (XfpmSuspend *suspend, - GError **error); - - -#define XFPM_SUSPEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), XFPM_TYPE_SUSPEND, XfpmSuspendPrivate)) - -struct XfpmSuspendPrivate -{ - /* sudo helper */ - HelperState helper_state; - pid_t helper_pid; - FILE *helper_infile; - FILE *helper_outfile; - guint helper_watchid; - gboolean helper_require_password; -}; - - -G_DEFINE_TYPE (XfpmSuspend, xfpm_suspend, G_TYPE_OBJECT) - -static void -xfpm_suspend_init (XfpmSuspend *suspend) -{ - GError *error = NULL; - - suspend->priv = XFPM_SUSPEND_GET_PRIVATE (suspend); - suspend->priv->helper_state = SUDO_NOT_INITIAZED; - suspend->priv->helper_require_password = FALSE; - suspend->priv->helper_infile = NULL; - suspend->priv->helper_outfile = NULL; - suspend->priv->helper_pid = 0; - suspend->priv->helper_watchid = 0; - - if (!xfpm_suspend_sudo_init (suspend, &error)) - { - g_warning ("xfpm_suspend_sudo_init failed : %s", error->message); - g_error_free (error); - } -} - -static void -xfpm_suspend_finalize (GObject *object) -{ - XfpmSuspend *suspend = XFPM_SUSPEND (object); - - /* close down helper */ - xfpm_suspend_sudo_free (suspend); - - G_OBJECT_CLASS (xfpm_suspend_parent_class)->finalize (object); -} - -static void -xfpm_suspend_class_init (XfpmSuspendClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = xfpm_suspend_finalize; - - g_type_class_add_private (klass, sizeof (XfpmSuspendPrivate)); -} - -XfpmSuspend * -xfpm_suspend_get (void) -{ - static gpointer xfpm_suspend_object = NULL; - - if ( G_LIKELY (xfpm_suspend_object != NULL ) ) - { - g_object_ref (xfpm_suspend_object); - } - else - { - xfpm_suspend_object = g_object_new (XFPM_TYPE_SUSPEND, NULL); - g_object_add_weak_pointer (xfpm_suspend_object, &xfpm_suspend_object); - } - - return XFPM_SUSPEND (xfpm_suspend_object); -} - -static void -xfpm_suspend_sudo_free (XfpmSuspend *suspend) -{ - gint status; - - /* close down helper */ - if (suspend->priv->helper_infile != NULL) - { - fclose (suspend->priv->helper_infile); - suspend->priv->helper_infile = NULL; - } - - if (suspend->priv->helper_outfile != NULL) - { - fclose (suspend->priv->helper_outfile); - suspend->priv->helper_outfile = NULL; - } - - if (suspend->priv->helper_watchid > 0) - { - g_source_remove (suspend->priv->helper_watchid); - suspend->priv->helper_watchid = 0; - } - - if (suspend->priv->helper_pid > 0) - { - waitpid (suspend->priv->helper_pid, &status, 0); - suspend->priv->helper_pid = 0; - } - - /* reset state */ - suspend->priv->helper_state = SUDO_NOT_INITIAZED; -} - -static void -xfpm_suspend_sudo_childwatch (GPid pid, - gint status, - gpointer data) -{ - /* close down sudo stuff */ - xfpm_suspend_sudo_free (XFPM_SUSPEND (data)); -} - -static gboolean -xfpm_suspend_sudo_init (XfpmSuspend *suspend, - GError **error) -{ - gchar *cmd; -#ifdef HAVE_SYS_RESOURCE_H - struct rlimit rlp; -#endif - gchar buf[15]; - gint parent_pipe[2]; - gint child_pipe[2]; - gint n; - - /* return state if we succeeded */ - if (suspend->priv->helper_state != SUDO_NOT_INITIAZED) - return suspend->priv->helper_state == SUDO_AVAILABLE; - - g_return_val_if_fail (suspend->priv->helper_infile == NULL, FALSE); - g_return_val_if_fail (suspend->priv->helper_outfile == NULL, FALSE); - g_return_val_if_fail (suspend->priv->helper_watchid == 0, FALSE); - g_return_val_if_fail (suspend->priv->helper_pid == 0, FALSE); - - /* assume it won't work for now */ - suspend->priv->helper_state = SUDO_FAILED; - - cmd = g_find_program_in_path ("sudo"); - if (G_UNLIKELY (cmd == NULL)) - { - g_set_error_literal (error, 1, 0, - "The program \"sudo\" was not found"); - return FALSE; - } - - if (pipe (parent_pipe) == -1) - { - g_set_error (error, 1, 0, - "Unable to create parent pipe: %s", - strerror (errno)); - goto err0; - } - - if (pipe (child_pipe) == -1) - { - g_set_error (error, 1, 0, - "Unable to create child pipe: %s", - strerror (errno)); - goto err1; - } - - suspend->priv->helper_pid = fork (); - if (suspend->priv->helper_pid < 0) - { - g_set_error (error, 1, 0, - "Unable to fork sudo helper: %s", - strerror (errno)); - goto err2; - } - else if (suspend->priv->helper_pid == 0) - { - /* setup signals */ - signal (SIGPIPE, SIG_IGN); - - /* setup environment */ - g_setenv ("LC_ALL", "C", TRUE); - g_setenv ("LANG", "C", TRUE); - g_setenv ("LANGUAGE", "C", TRUE); - - /* setup the 3 standard file handles */ - dup2 (child_pipe[0], STDIN_FILENO); - dup2 (parent_pipe[1], STDOUT_FILENO); - dup2 (parent_pipe[1], STDERR_FILENO); - -#ifdef HAVE_SYS_RESOURCE_H - /* close all other file handles */ - getrlimit (RLIMIT_NOFILE, &rlp); - for (n = 0; n < (gint) rlp.rlim_cur; ++n) - { - if (n != STDIN_FILENO && n != STDOUT_FILENO && n != STDERR_FILENO) - close (n); - } -#endif - - /* execute sudo with the helper */ - execl (cmd, "sudo", "-H", "-S", "-p", - "XFPM_SUDO_PASS ", "--", - XFPM_SUSPEND_HELPER_CMD, NULL); - - g_free (cmd); - cmd = NULL; - - _exit (127); - } - else - { - /* watch the sudo helper */ - suspend->priv->helper_watchid = g_child_watch_add (suspend->priv->helper_pid, - xfpm_suspend_sudo_childwatch, - suspend); - } - - /* read sudo/helper answer */ - n = read (parent_pipe[0], buf, sizeof (buf)); - if (n < 15) - { - g_set_error (error, 1, 0, - "Unable to read response from sudo helper: %s", - n < 0 ? strerror (errno) : "Unknown error"); - goto err2; - } - - /* open pipe to receive replies from sudo */ - suspend->priv->helper_infile = fdopen (parent_pipe[0], "r"); - if (suspend->priv->helper_infile == NULL) - { - g_set_error (error, 1, 0, - "Unable to open parent pipe: %s", - strerror (errno)); - goto err2; - } - close (parent_pipe[1]); - - /* open pipe to send passwords to sudo */ - suspend->priv->helper_outfile = fdopen (child_pipe[1], "w"); - if (suspend->priv->helper_outfile == NULL) - { - g_set_error (error, 1, 0, - "Unable to open parent pipe: %s", - strerror (errno)); - goto err2; - } - close (child_pipe[0]); - - /* check if NOPASSWD is set in /etc/sudoers */ - if (memcmp (buf, "XFPM_SUDO_PASS ", 15) == 0) - { - suspend->priv->helper_require_password = TRUE; - } - else if (memcmp (buf, "XFPM_SUDO_DONE ", 15) == 0) - { - suspend->priv->helper_require_password = FALSE; - } - else - { - g_set_error (error, 1, 0, - "Got unexpected reply from sudo pm helper"); - goto err2; - } - - XFPM_DEBUG ("suspend->priv->helper_require_password %s", - suspend->priv->helper_require_password ? "Required" : "Not required"); - - /* if we try again */ - suspend->priv->helper_state = SUDO_AVAILABLE; - - return TRUE; - -err2: - xfpm_suspend_sudo_free (suspend); - - close (child_pipe[0]); - close (child_pipe[1]); - -err1: - close (parent_pipe[0]); - close (parent_pipe[1]); - -err0: - g_free (cmd); - - suspend->priv->helper_pid = 0; - - return FALSE; -} - -gboolean -xfpm_suspend_sudo_try_action (XfpmSuspend *suspend, - XfpmActionType type, - GError **error) -{ - const gchar *action; - gchar reply[256]; - - TRACE("entering"); - - g_return_val_if_fail (suspend->priv->helper_state == SUDO_AVAILABLE, FALSE); - g_return_val_if_fail (suspend->priv->helper_outfile != NULL, FALSE); - g_return_val_if_fail (suspend->priv->helper_infile != NULL, FALSE); - - /* the command we send to sudo */ - if (type == XFPM_SUSPEND) - action = "SUSPEND"; - else if (type == XFPM_HIBERNATE) - action = "HIBERNATE"; - else - return FALSE; - - /* write action to sudo helper */ - if (fprintf (suspend->priv->helper_outfile, "%s\n", action) > 0) - fflush (suspend->priv->helper_outfile); - - /* check if the write succeeded */ - if (ferror (suspend->priv->helper_outfile) != 0) - { - /* probably succeeded but the helper got killed */ - if (errno == EINTR) - return TRUE; - - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), - _("Error sending command to pm helper: %s"), - strerror (errno)); - return FALSE; - } - - /* get responce from sudo helper */ - if (fgets (reply, sizeof (reply), suspend->priv->helper_infile) == NULL) - { - /* probably succeeded but the helper got killed */ - if (errno == EINTR) - return TRUE; - - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), - _("Error receiving response from pm helper: %s"), - strerror (errno)); - return FALSE; - } - - if (strncmp (reply, "SUCCEED", 7) != 0) - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, - _("Sleep command failed")); - - return FALSE; - } - - return TRUE; -} - -XfpmPassState -xfpm_suspend_sudo_send_password (XfpmSuspend *suspend, - const gchar *password) -{ - gchar buf[1024]; - gsize len_buf, len_send; - gint fd; - gsize len; - gssize result; - gint attempts; - const gchar *errmsg = NULL; - - g_return_val_if_fail (suspend->priv->helper_state == SUDO_AVAILABLE, PASSWORD_FAILED); - g_return_val_if_fail (suspend->priv->helper_outfile != NULL, PASSWORD_FAILED); - g_return_val_if_fail (suspend->priv->helper_infile != NULL, PASSWORD_FAILED); - g_return_val_if_fail (suspend->priv->helper_require_password, PASSWORD_FAILED); - g_return_val_if_fail (password != NULL, PASSWORD_FAILED); - - /* write password to sudo helper */ - g_snprintf (buf, sizeof (buf), "%s\n", password); - len_buf = strlen (buf); - len_send = fwrite (buf, 1, len_buf, suspend->priv->helper_outfile); - fflush (suspend->priv->helper_outfile); - bzero (buf, len_buf); - - if (len_send != len_buf || ferror (suspend->priv->helper_outfile) != 0) - { - errmsg = "Failed to send password to sudo"; - goto err1; - } - - fd = fileno (suspend->priv->helper_infile); - - for (len = 0, attempts = 0;;) - { - result = read (fd, buf + len, 256 - len); - - if (result < 0) - { - errmsg = "Failed to read data from sudo"; - goto err1; - } - else if (result == 0) - { - /* don't try too often */ - if (++attempts > 20) - { - errmsg = "Too many password attempts"; - goto err1; - } - - continue; - } - else if (result + len >= sizeof (buf)) - { - errmsg = "Received too much data from sudo"; - goto err1; - } - - len += result; - buf[len] = '\0'; - - if (len >= 15) - { - if (g_str_has_suffix (buf, "XFPM_SUDO_PASS ")) - { - return PASSWORD_RETRY; - } - else if (g_str_has_suffix (buf, "XFPM_SUDO_DONE ")) - { - /* sudo is unlocked, no further passwords required */ - suspend->priv->helper_require_password = FALSE; - - return PASSWORD_SUCCEED; - } - } - } - - return PASSWORD_FAILED; - -err1: - g_printerr (PACKAGE_NAME ": %s.\n\n", errmsg); - return PASSWORD_FAILED; -} - -gboolean -xfpm_suspend_password_required (XfpmSuspend *suspend) -{ - g_return_val_if_fail (XFPM_IS_SUSPEND (suspend), TRUE); - - return suspend->priv->helper_require_password; -} - -HelperState -xfpm_suspend_sudo_get_state (XfpmSuspend *suspend) -{ - g_return_val_if_fail (XFPM_IS_SUSPEND (suspend), SUDO_NOT_INITIAZED); - - return suspend->priv->helper_state; -} - - - #ifdef BACKEND_TYPE_FREEBSD static gchar * @@ -627,8 +159,43 @@ xfpm_suspend_can_hibernate (void) return linux_supports_sleep_state ("hibernate"); #endif #ifdef BACKEND_TYPE_OPENBSD - return FALSE; + return TRUE; #endif return FALSE; } + +gboolean +xfpm_suspend_try_action (XfpmActionType type) +{ + const gchar *action; + gboolean ret; + GError *error = NULL; + gint exit_status = 0; + gchar *command = NULL; + + TRACE("entering"); + + if (type == XFPM_SUSPEND) + action = "suspend"; + else if (type == XFPM_HIBERNATE) + action = "hibernate"; + else + return FALSE; + + command = g_strdup_printf ("pkexec " SBINDIR "/xfpm-pm-helper --%s", action); + ret = g_spawn_command_line_sync (command, NULL, NULL, &exit_status, &error); + if ( !ret ) + { + g_warning ("xfpm_brightness_helper_set_level: failed to set value: %s", error->message); + g_error_free (error); + } + else + { + g_debug ("executed %s; retval: %i", command, exit_status); + ret = (exit_status == 0); + } + + g_free (command); + return ret; +} diff --git a/src/xfpm-suspend.h b/src/xfpm-suspend.h index f012e69..02dfa47 100644 --- a/src/xfpm-suspend.h +++ b/src/xfpm-suspend.h @@ -22,32 +22,6 @@ #include -G_BEGIN_DECLS - -#define XFPM_TYPE_SUSPEND (xfpm_suspend_get_type () ) -#define XFPM_SUSPEND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XFPM_TYPE_SUSPEND, XfpmSuspend)) -#define XFPM_IS_SUSPEND(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XFPM_TYPE_SUSPEND)) - -typedef struct XfpmSuspendPrivate XfpmSuspendPrivate; - -typedef struct -{ - GObject parent; - XfpmSuspendPrivate *priv; -} XfpmSuspend; - -typedef struct -{ - GObjectClass parent_class; -} XfpmSuspendClass; - -typedef enum -{ - SUDO_NOT_INITIAZED, - SUDO_AVAILABLE, - SUDO_FAILED -} HelperState; - typedef enum { XFPM_ASK_0 = 0, @@ -55,31 +29,9 @@ typedef enum XFPM_HIBERNATE, } XfpmActionType; -typedef enum -{ - PASSWORD_RETRY, - PASSWORD_SUCCEED, - PASSWORD_FAILED -} XfpmPassState; - -GType xfpm_suspend_get_type (void) G_GNUC_CONST; - -XfpmSuspend *xfpm_suspend_get (void); - gboolean xfpm_suspend_can_suspend (void); gboolean xfpm_suspend_can_hibernate (void); -gboolean xfpm_suspend_password_required (XfpmSuspend *suspend); - -gboolean xfpm_suspend_sudo_try_action (XfpmSuspend *suspend, - XfpmActionType type, - GError **error); - -XfpmPassState xfpm_suspend_sudo_send_password (XfpmSuspend *suspend, - const gchar *password); - -HelperState xfpm_suspend_sudo_get_state (XfpmSuspend *suspend); - -G_END_DECLS +gboolean xfpm_suspend_try_action (XfpmActionType type); #endif /* __XFPM_SUSPEND_H */ -- 2.0.4