2
* Copyright (C) 2009 Red Hat, Inc.
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General
15
* Public License along with this library; if not, write to the
16
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
* Boston, MA 02110-1301, USA.
19
* Author: David Zeuthen <davidz@redhat.com>
26
#include <sys/types.h>
28
#include <glib/gi18n.h>
30
#include <polkit/polkit.h>
31
#include <polkitagent/polkitagent.h>
33
#include "polkitgnomeauthenticator.h"
34
#include "polkitgnomeauthenticationdialog.h"
36
struct _PolkitGnomeAuthenticator
38
GObject parent_instance;
40
PolkitAuthority *authority;
44
PolkitDetails *details;
48
PolkitActionDescription *action_desc;
51
gboolean gained_authorization;
52
gboolean was_cancelled;
53
gboolean new_user_selected;
56
PolkitAgentSession *session;
61
struct _PolkitGnomeAuthenticatorClass
63
GObjectClass parent_class;
73
static guint signals[LAST_SIGNAL] = {0};
75
G_DEFINE_TYPE (PolkitGnomeAuthenticator, polkit_gnome_authenticator, G_TYPE_OBJECT);
78
polkit_gnome_authenticator_init (PolkitGnomeAuthenticator *authenticator)
83
polkit_gnome_authenticator_finalize (GObject *object)
85
PolkitGnomeAuthenticator *authenticator;
87
authenticator = POLKIT_GNOME_AUTHENTICATOR (object);
89
if (authenticator->authority != NULL)
90
g_object_unref (authenticator->authority);
91
g_free (authenticator->action_id);
92
g_free (authenticator->message);
93
g_free (authenticator->icon_name);
94
if (authenticator->details != NULL)
95
g_object_unref (authenticator->details);
96
g_free (authenticator->cookie);
97
g_list_foreach (authenticator->identities, (GFunc) g_object_unref, NULL);
98
g_list_free (authenticator->identities);
100
if (authenticator->action_desc != NULL)
101
g_object_unref (authenticator->action_desc);
102
g_strfreev (authenticator->users);
104
g_free (authenticator->selected_user);
105
if (authenticator->session != NULL)
106
g_object_unref (authenticator->session);
107
if (authenticator->dialog != NULL)
108
gtk_widget_destroy (authenticator->dialog);
109
if (authenticator->loop != NULL)
110
g_main_loop_unref (authenticator->loop);
112
if (G_OBJECT_CLASS (polkit_gnome_authenticator_parent_class)->finalize != NULL)
113
G_OBJECT_CLASS (polkit_gnome_authenticator_parent_class)->finalize (object);
117
polkit_gnome_authenticator_class_init (PolkitGnomeAuthenticatorClass *klass)
119
GObjectClass *gobject_class;
121
gobject_class = G_OBJECT_CLASS (klass);
123
gobject_class->finalize = polkit_gnome_authenticator_finalize;
126
* PolkitGnomeAuthenticator::completed:
127
* @authenticator: A #PolkitGnomeAuthenticator.
128
* @gained_authorization: Whether the authorization was gained.
129
* @dismissed: Whether the dialog was dismissed.
131
* Emitted when the authentication is completed. The user is supposed to dispose of @authenticator
132
* upon receiving this signal.
134
signals[COMPLETED_SIGNAL] = g_signal_new ("completed",
135
POLKIT_GNOME_TYPE_AUTHENTICATOR,
137
0, /* class offset */
138
NULL, /* accumulator */
139
NULL, /* accumulator data */
140
g_cclosure_marshal_generic,
147
static PolkitActionDescription *
148
get_desc_for_action (PolkitAuthority *authority,
149
const gchar *action_id)
153
PolkitActionDescription *result;
157
action_descs = polkit_authority_enumerate_actions_sync (authority,
160
for (l = action_descs; l != NULL; l = l->next)
162
PolkitActionDescription *action_desc = POLKIT_ACTION_DESCRIPTION (l->data);
164
if (strcmp (polkit_action_description_get_action_id (action_desc), action_id) == 0)
166
result = g_object_ref (action_desc);
173
g_list_foreach (action_descs, (GFunc) g_object_unref, NULL);
174
g_list_free (action_descs);
180
on_dialog_deleted (GtkWidget *widget,
184
PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
186
polkit_gnome_authenticator_cancel (authenticator);
190
on_user_selected (GObject *object,
194
PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
196
/* clear any previous messages */
197
polkit_gnome_authentication_dialog_set_info_message (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog), "");
199
polkit_gnome_authenticator_cancel (authenticator);
200
authenticator->new_user_selected = TRUE;
203
PolkitGnomeAuthenticator *
204
polkit_gnome_authenticator_new (const gchar *action_id,
205
const gchar *message,
206
const gchar *icon_name,
207
PolkitDetails *details,
211
PolkitGnomeAuthenticator *authenticator;
216
authenticator = POLKIT_GNOME_AUTHENTICATOR (g_object_new (POLKIT_GNOME_TYPE_AUTHENTICATOR, NULL));
219
authenticator->authority = polkit_authority_get_sync (NULL /* GCancellable* */, &error);
220
if (authenticator->authority == NULL)
222
g_critical ("Error getting authority: %s", error->message);
223
g_error_free (error);
227
authenticator->action_id = g_strdup (action_id);
228
authenticator->message = g_strdup (message);
229
authenticator->icon_name = g_strdup (icon_name);
231
authenticator->details = g_object_ref (details);
232
authenticator->cookie = g_strdup (cookie);
233
authenticator->identities = g_list_copy (identities);
234
g_list_foreach (authenticator->identities, (GFunc) g_object_ref, NULL);
236
authenticator->action_desc = get_desc_for_action (authenticator->authority,
237
authenticator->action_id);
238
if (authenticator->action_desc == NULL)
241
authenticator->users = g_new0 (gchar *, g_list_length (authenticator->identities) + 1);
242
for (l = authenticator->identities, n = 0; l != NULL; l = l->next, n++)
244
PolkitUnixUser *user = POLKIT_UNIX_USER (l->data);
246
struct passwd *passwd;
248
uid = polkit_unix_user_get_uid (user);
249
passwd = getpwuid (uid);
250
authenticator->users[n] = g_strdup (passwd->pw_name);
253
authenticator->dialog = polkit_gnome_authentication_dialog_new
254
(authenticator->action_id,
255
polkit_action_description_get_vendor_name (authenticator->action_desc),
256
polkit_action_description_get_vendor_url (authenticator->action_desc),
257
authenticator->icon_name,
258
authenticator->message,
259
authenticator->details,
260
authenticator->users);
261
g_signal_connect (authenticator->dialog,
263
G_CALLBACK (on_dialog_deleted),
265
g_signal_connect (authenticator->dialog,
266
"notify::selected-user",
267
G_CALLBACK (on_user_selected),
270
return authenticator;
273
g_object_unref (authenticator);
278
session_request (PolkitAgentSession *session,
283
PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
285
gchar *modified_request;
289
//g_debug ("in conversation_pam_prompt, request='%s', echo_on=%d", request, echo_on);
291
/* Fix up, and localize, password prompt if it's password auth */
292
if (g_ascii_strncasecmp (request, "password:", 9) == 0)
294
if (strcmp (g_get_user_name (), authenticator->selected_user) != 0)
296
modified_request = g_strdup_printf (_("_Password for %s:"), authenticator->selected_user);
300
modified_request = g_strdup (_("_Password:"));
305
modified_request = g_strdup (request);
308
gtk_widget_show_all (GTK_WIDGET (authenticator->dialog));
309
gtk_window_present (GTK_WINDOW (authenticator->dialog));
310
password = polkit_gnome_authentication_dialog_run_until_response_for_prompt (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog),
313
&authenticator->was_cancelled,
314
&authenticator->new_user_selected);
316
/* cancel auth unless user provided a password */
317
if (password == NULL)
319
polkit_gnome_authenticator_cancel (authenticator);
324
polkit_agent_session_response (authenticator->session, password);
329
g_free (modified_request);
333
session_show_error (PolkitAgentSession *session,
337
PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
340
s = g_strconcat ("<b>", msg, "</b>", NULL);
341
polkit_gnome_authentication_dialog_set_info_message (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog), s);
346
session_show_info (PolkitAgentSession *session,
350
PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
353
s = g_strconcat ("<b>", msg, "</b>", NULL);
354
polkit_gnome_authentication_dialog_set_info_message (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog), s);
357
gtk_widget_show_all (GTK_WIDGET (authenticator->dialog));
358
gtk_window_present (GTK_WINDOW (authenticator->dialog));
363
session_completed (PolkitAgentSession *session,
364
gboolean gained_authorization,
367
PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
369
authenticator->gained_authorization = gained_authorization;
371
//g_debug ("in conversation_done gained=%d", gained_authorization);
373
g_main_loop_quit (authenticator->loop);
378
do_initiate (gpointer user_data)
380
PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
381
PolkitIdentity *identity;
384
gtk_widget_show_all (GTK_WIDGET (authenticator->dialog));
385
gtk_window_present (GTK_WINDOW (authenticator->dialog));
386
if (!polkit_gnome_authentication_dialog_run_until_user_is_selected (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog)))
388
/* user cancelled the dialog */
389
/*g_debug ("User cancelled before selecting a user");*/
390
authenticator->was_cancelled = TRUE;
394
authenticator->loop = g_main_loop_new (NULL, TRUE);
400
g_free (authenticator->selected_user);
401
authenticator->selected_user = polkit_gnome_authentication_dialog_get_selected_user (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog));
403
/*g_debug ("Authenticating user %s", authenticator->selected_user);*/
404
identity = polkit_unix_user_new_for_name (authenticator->selected_user, NULL);
406
authenticator->session = polkit_agent_session_new (identity, authenticator->cookie);
408
g_object_unref (identity);
410
g_signal_connect (authenticator->session,
412
G_CALLBACK (session_request),
415
g_signal_connect (authenticator->session,
417
G_CALLBACK (session_show_info),
420
g_signal_connect (authenticator->session,
422
G_CALLBACK (session_show_error),
425
g_signal_connect (authenticator->session,
427
G_CALLBACK (session_completed),
430
polkit_agent_session_initiate (authenticator->session);
432
g_main_loop_run (authenticator->loop);
434
/*g_debug ("gained_authorization=%d was_cancelled=%d new_user_selected=%d.",
435
authenticator->gained_authorization,
436
authenticator->was_cancelled,
437
authenticator->new_user_selected);*/
439
if (authenticator->new_user_selected)
441
/*g_debug ("New user selected");*/
442
authenticator->new_user_selected = FALSE;
443
g_object_unref (authenticator->session);
444
authenticator->session = NULL;
450
if (!authenticator->gained_authorization && !authenticator->was_cancelled)
452
if (authenticator->dialog != NULL)
456
s = g_strconcat ("<b>", _("Authentication Failure"), "</b>", NULL);
457
polkit_gnome_authentication_dialog_set_info_message (
458
POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog),
461
gtk_widget_queue_draw (authenticator->dialog);
463
/* shake the dialog to indicate error */
464
polkit_gnome_authentication_dialog_indicate_error (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog));
468
g_object_unref (authenticator->session);
469
authenticator->session = NULL;
476
g_signal_emit_by_name (authenticator,
478
authenticator->gained_authorization,
479
authenticator->was_cancelled);
481
g_object_unref (authenticator);
487
polkit_gnome_authenticator_initiate (PolkitGnomeAuthenticator *authenticator)
489
/* run from idle since we're going to block the main loop in the dialog (which has a recursive mainloop) */
490
g_idle_add (do_initiate, g_object_ref (authenticator));
494
polkit_gnome_authenticator_cancel (PolkitGnomeAuthenticator *authenticator)
496
if (authenticator->dialog != NULL)
497
polkit_gnome_authentication_dialog_cancel (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog));
499
authenticator->was_cancelled = TRUE;
501
if (authenticator->session != NULL)
503
polkit_agent_session_cancel (authenticator->session);
508
polkit_gnome_authenticator_get_cookie (PolkitGnomeAuthenticator *authenticator)
510
return authenticator->cookie;