--- gksu-2.0.2/gksu/gksu.c-orig 2010-12-16 03:43:51.275486079 -0600 +++ gksu-2.0.2/gksu/gksu.c 2010-12-16 03:46:11.151315385 -0600 @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include @@ -27,6 +29,9 @@ gboolean print_pass = FALSE; gboolean force_grab = FALSE; gboolean prompt = FALSE; +gboolean elevated_privilege = TRUE; +gboolean elevated_role = TRUE; + enum { SUDO_MODE, @@ -40,10 +45,14 @@ struct option long_opts[] = { */ {"help", no_argument, NULL, 'h'}, {"login", no_argument, NULL, 'l'}, +#ifndef __sun {"preserv-env", no_argument, NULL, 'k'}, {"preserve-env", no_argument, NULL, 'k'}, +#endif {"user", required_argument, NULL, 'u'}, +#ifndef __sun {"print-pass", no_argument, NULL, 'p'}, +#endif {"message", required_argument, NULL, 'm'}, {"title", required_argument, NULL, 't'}, {"icon", required_argument, NULL, 'i'}, @@ -55,6 +64,8 @@ struct option long_opts[] = { {"prompt", optional_argument, NULL, 'P'}, {"desktop", required_argument, NULL, 'D'}, {"description", required_argument, NULL, 'D'}, + {"elevated-privilege", no_argument, NULL, 'p'}, + {"elevated-role", no_argument, NULL, 'r'}, {0, 0, 0, 0} }; @@ -106,12 +117,14 @@ help (gchar *cmdname) " Replace the standard message shown to ask for\n" " password for the argument passed to the option.\n" " Only use this if --description does not suffice.\n"), +#ifndef __sun N_("\n"), N_(" --print-pass, -p\n" " Ask gksu to print the password to stdout, just\n" " like ssh-askpass. Useful to use in scripts with\n" " programs that accept receiving the password on\n" " stdin.\n"), +#endif N_("\n"), N_(" --sudo-mode, -S\n" " Make GKSu use sudo instead of su, as if it had been\n" @@ -119,6 +132,13 @@ help (gchar *cmdname) N_(" --su-mode, -w\n" " Make GKSu use su, instead of using libgksu's\n" " default.\n"), +#ifdef __sun + N_("\n"), + N_(" --elevated-privilege, -p\n" + " attempt to elevate user's privilege\n"), + N_(" --elevated-role, -r\n" + " attempt to elevate user's role\n"), +#endif }; help_trans = g_strconcat(_(help_text[0]), _(help_text[1]), @@ -157,6 +177,14 @@ gk_dialog (GtkMessageType type, gchar *f gtk_window_set_resizable (GTK_WINDOW(diag_win), FALSE); gtk_widget_show_all (diag_win); + + // we "raise" the window because there is a race here for + // focus-follow-mouse and auto-raise WMs that may put the window + // in the background and confuse users + gtk_window_set_keep_above(GTK_WINDOW (diag_win), TRUE); + // reset cursor + gdk_window_set_cursor(diag_win->window, gdk_cursor_new(GDK_LEFT_PTR)); + gtk_dialog_run (GTK_DIALOG(diag_win)); g_free (msg); @@ -271,10 +299,12 @@ show_hide_advanced (GtkWidget *button, g else gksu_context_set_login_shell (context, FALSE); +#ifndef __sun if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(check_presenv))) gksu_context_set_keep_env (context, TRUE); else gksu_context_set_keep_env (context, FALSE); +#endif gtk_widget_destroy (dialog); } @@ -334,8 +364,15 @@ fill_with_user_list(GtkWidget *combobox) endpwent(); } +static gboolean +focus_out_cb (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) +{ + gtk_window_present (GTK_WINDOW(widget)); + return TRUE; +} + void -request_command_and_user (GksuContext *context) +request_command_and_user (GksuContext *context, gchar *command) { GtkWidget *dialog; GtkWidget *hbox; @@ -347,7 +384,12 @@ request_command_and_user (GksuContext *c GtkWidget *entry_cmd; GtkWidget *label_user; - GtkWidget *combo_user; + GtkWidget *entry_user; + + AtkObject *atk_user_label; + AtkObject *atk_user_entry; + AtkObject *atk_command_label; + AtkObject *atk_command_entry; /* advanced stuff */ GtkWidget *advanced_button; @@ -362,6 +404,11 @@ request_command_and_user (GksuContext *c GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); + + /* make sure that our window will always have the focus */ + g_signal_connect (G_OBJECT(dialog), "focus-out-event", + G_CALLBACK(focus_out_cb), NULL); + gtk_dialog_set_has_separator (GTK_DIALOG(dialog), FALSE); /* horizontal box */ @@ -385,14 +432,44 @@ request_command_and_user (GksuContext *c dialog); gtk_box_pack_start (GTK_BOX(lvbox), entry_cmd, TRUE, TRUE, 0); + if (command) + { + gtk_entry_set_text (GTK_ENTRY (entry_cmd), command); + gtk_editable_set_editable (GTK_EDITABLE (entry_cmd), FALSE); + gtk_widget_set_sensitive (entry_cmd, FALSE); + } + + atk_command_label = gtk_widget_get_accessible (label_cmd); + atk_command_entry = gtk_widget_get_accessible (entry_cmd); + atk_object_add_relationship (atk_command_label, ATK_RELATION_LABEL_FOR, + atk_command_entry); + atk_object_add_relationship (atk_command_entry, ATK_RELATION_LABELLED_BY, + atk_command_label); + /* user name */ - label_user = gtk_label_new (_("As user:")); + /* SUN_BRANDING label */ + label_user = gtk_label_new (_("As user or role:")); gtk_label_set_justify (GTK_LABEL(label_user), GTK_JUSTIFY_LEFT); gtk_box_pack_start (GTK_BOX(lvbox), label_user, TRUE, TRUE, 0); - combo_user = gtk_combo_box_new_text (); - fill_with_user_list (combo_user); - gtk_box_pack_start (GTK_BOX(lvbox), combo_user, TRUE, TRUE, 0); + entry_user = gtk_entry_new (); + gtk_signal_connect (GTK_OBJECT(entry_user), "activate", + GTK_SIGNAL_FUNC(response_ok_cb), + dialog); + + if (context->user) + { + gtk_entry_set_text (GTK_ENTRY (entry_user), context->user); + } + + atk_user_label = gtk_widget_get_accessible (label_user); + atk_user_entry = gtk_widget_get_accessible (entry_user); + atk_object_add_relationship (atk_user_label, ATK_RELATION_LABEL_FOR, + atk_user_entry); + atk_object_add_relationship (atk_user_entry, ATK_RELATION_LABELLED_BY, + atk_user_label); + + gtk_box_pack_start (GTK_BOX(lvbox), entry_user, TRUE, TRUE, 0); /* right vertical box */ rvbox = gtk_vbox_new (FALSE, 2); @@ -430,18 +507,14 @@ request_command_and_user (GksuContext *c g_free (tmp); } - tmp = gtk_combo_box_get_active_text (GTK_COMBO_BOX(combo_user)); + tmp = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry_user))); if (tmp) { gksu_context_set_user (context, tmp); g_free (tmp); } - if (!strcmp (gksu_context_get_user (context), "")) - { - gk_dialog (GTK_MESSAGE_ERROR, _("Missing command to run.")); - } - else + if (strcmp (gksu_context_get_user (context), "")) { gtk_widget_destroy (dialog); break; @@ -502,7 +575,13 @@ main (int argc, char **argv) gtk_init (&newargc, &newargv); context = gksu_context_new (); - while ((c = getopt_long(newargc, newargv, "?hu:lpm:kt:i:gdsSwP::aD:", long_opts, NULL)) + /* + * First character is + since we want gksu to accept all arguments after the + * first operand as part of the operand. So you can run + * "gksu -u root command -x". Without the "+", getopt_long incorrectly + * treats the "-x" as a gksu argument rather than a command argument. + */ + while ((c = getopt_long(newargc, newargv, "+?hu:lpm:kt:i:gdsSwP::aD:", long_opts, NULL)) != EOF) { switch (c) @@ -525,14 +604,20 @@ main (int argc, char **argv) gksu_context_set_login_shell (context, TRUE); break; case 'p': +#ifndef __sun print_pass = TRUE; +#else + gksu_context_set_elevated_privilege (context, FALSE); +#endif break; case 'm': gksu_context_set_message (context, optarg); break; +#ifndef __sun case 'k': gksu_context_set_keep_env (context, TRUE); break; +#endif case 'g': gksu_context_set_grab (context, FALSE); @@ -565,6 +650,9 @@ main (int argc, char **argv) case 'w': run_mode = SU_MODE; break; + case 'r': + gksu_context_set_elevated_role (context, FALSE); + break; case 'P': prompt = TRUE; @@ -646,9 +734,14 @@ main (int argc, char **argv) return 0; } + if (gksu_context_get_pfexec_mode (context)) + { + gksu_context_set_need_pipe (context, FALSE); + } + /* now we can begin to care about a command */ if (newargc <= optind) - request_command_and_user (context); /* previously known as gksuexec */ + request_command_and_user (context, NULL); /* previously known as gksuexec */ else { gchar *command = g_strdup (newargv[optind]); @@ -693,7 +786,27 @@ main (int argc, char **argv) g_free (command); command = tmp; } - gksu_context_set_command (context, command); + + context->command = g_strdup (command); + + if (strcmp (g_get_user_name (), "root") == 0) + { + /* If root, just use pfexec */ + context->pfexec_mode = TRUE; + context->user = g_strdup ("root"); + } + else if (run_mode != SUDO_MODE) + { + if (gksu_context_try_need_password (context)) + { + request_command_and_user (context, command); + } + } + else + { + request_command_and_user (context, command); + } + g_free (command); } @@ -714,7 +827,8 @@ main (int argc, char **argv) return 1; } - if (pwentry->pw_uid == geteuid ()) + /* If in pfexec mode, process in gksu_sudo_fuller */ + if (!gksu_context_get_pfexec_mode (context) && pwentry->pw_uid == geteuid ()) { gint retval = g_spawn_command_line_sync (gksu_context_get_command (context), NULL, NULL, NULL, NULL); @@ -722,18 +836,6 @@ main (int argc, char **argv) } } - { - gint count = 0; - - for (count = 0; count < 3; count++) - { - if (error) /* wrong password was given */ - { - gksu_context_set_alert (context, _("Incorrect password... try again.")); - g_error_free (error); - error = NULL; - } - if (run_mode == SUDO_MODE) gksu_sudo_fuller (context, NULL, NULL, @@ -753,18 +855,25 @@ main (int argc, char **argv) NULL, NULL, &exit_status, &error); - if ((error == NULL) || (error->code != GKSU_ERROR_WRONGPASS)) - break; - } - } if (error && (error->code != GKSU_ERROR_CANCELED)) { + char *msg; + + if (context->alert != NULL) + { + msg = context->alert; + } + else + { + msg = error->message; + } + gk_dialog (GTK_MESSAGE_ERROR, _("Failed to run %s as user %s.\n\n%s"), gksu_context_get_command (context), gksu_context_get_user (context), - error->message); + msg); return 3; }