~ubuntu-branches/ubuntu/precise/policykit-1-gnome/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/0001-Revert-Drop-marshaller-complications.patch/src/polkitgnomeauthenticator.c

  • Committer: Package Import Robot
  • Author(s): Michael Terry
  • Date: 2011-12-19 09:25:17 UTC
  • mfrom: (7.2.8 sid)
  • Revision ID: package-import@ubuntu.com-20111219092517-f8nm89u8lek9xo3e
Tags: 0.105-1ubuntu1
* Merge with Debian testing, remaining changes:
  - 04-autorestart.patch: Add gnome session restart support to ensure we
    always have an authentication agent running. To be forwarded upstream.
  - 06-authentication-failure-string.patch: Improve error message displayed
    when authentication fails.
  - Tell the .desktop file for the authentication agent to auto-restart the
    agent in case of failure.
* debian/patches/04-autorestart.patch:
  - Update to use GDBus instead of DBusGLib

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2009 Red Hat, Inc.
 
3
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
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.
 
18
 *
 
19
 * Author: David Zeuthen <davidz@redhat.com>
 
20
 */
 
21
 
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <string.h>
 
26
#include <sys/types.h>
 
27
#include <pwd.h>
 
28
#include <glib/gi18n.h>
 
29
 
 
30
#include <polkit/polkit.h>
 
31
#include <polkitagent/polkitagent.h>
 
32
 
 
33
#include "polkitgnomeauthenticator.h"
 
34
#include "polkitgnomeauthenticationdialog.h"
 
35
 
 
36
struct _PolkitGnomeAuthenticator
 
37
{
 
38
  GObject parent_instance;
 
39
 
 
40
  PolkitAuthority *authority;
 
41
  gchar *action_id;
 
42
  gchar *message;
 
43
  gchar *icon_name;
 
44
  PolkitDetails *details;
 
45
  gchar *cookie;
 
46
  GList *identities;
 
47
 
 
48
  PolkitActionDescription *action_desc;
 
49
  gchar **users;
 
50
 
 
51
  gboolean gained_authorization;
 
52
  gboolean was_cancelled;
 
53
  gboolean new_user_selected;
 
54
  gchar *selected_user;
 
55
 
 
56
  PolkitAgentSession *session;
 
57
  GtkWidget *dialog;
 
58
  GMainLoop *loop;
 
59
};
 
60
 
 
61
struct _PolkitGnomeAuthenticatorClass
 
62
{
 
63
  GObjectClass parent_class;
 
64
 
 
65
};
 
66
 
 
67
enum
 
68
{
 
69
  COMPLETED_SIGNAL,
 
70
  LAST_SIGNAL,
 
71
};
 
72
 
 
73
static guint signals[LAST_SIGNAL] = {0};
 
74
 
 
75
G_DEFINE_TYPE (PolkitGnomeAuthenticator, polkit_gnome_authenticator, G_TYPE_OBJECT);
 
76
 
 
77
static void
 
78
polkit_gnome_authenticator_init (PolkitGnomeAuthenticator *authenticator)
 
79
{
 
80
}
 
81
 
 
82
static void
 
83
polkit_gnome_authenticator_finalize (GObject *object)
 
84
{
 
85
  PolkitGnomeAuthenticator *authenticator;
 
86
 
 
87
  authenticator = POLKIT_GNOME_AUTHENTICATOR (object);
 
88
 
 
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);
 
99
 
 
100
  if (authenticator->action_desc != NULL)
 
101
    g_object_unref (authenticator->action_desc);
 
102
  g_strfreev (authenticator->users);
 
103
 
 
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);
 
111
 
 
112
  if (G_OBJECT_CLASS (polkit_gnome_authenticator_parent_class)->finalize != NULL)
 
113
    G_OBJECT_CLASS (polkit_gnome_authenticator_parent_class)->finalize (object);
 
114
}
 
115
 
 
116
static void
 
117
polkit_gnome_authenticator_class_init (PolkitGnomeAuthenticatorClass *klass)
 
118
{
 
119
  GObjectClass *gobject_class;
 
120
 
 
121
  gobject_class = G_OBJECT_CLASS (klass);
 
122
 
 
123
  gobject_class->finalize = polkit_gnome_authenticator_finalize;
 
124
 
 
125
  /**
 
126
   * PolkitGnomeAuthenticator::completed:
 
127
   * @authenticator: A #PolkitGnomeAuthenticator.
 
128
   * @gained_authorization: Whether the authorization was gained.
 
129
   * @dismissed: Whether the dialog was dismissed.
 
130
   *
 
131
   * Emitted when the authentication is completed. The user is supposed to dispose of @authenticator
 
132
   * upon receiving this signal.
 
133
   **/
 
134
  signals[COMPLETED_SIGNAL] = g_signal_new ("completed",
 
135
                                            POLKIT_GNOME_TYPE_AUTHENTICATOR,
 
136
                                            G_SIGNAL_RUN_LAST,
 
137
                                            0,                      /* class offset     */
 
138
                                            NULL,                   /* accumulator      */
 
139
                                            NULL,                   /* accumulator data */
 
140
                                            g_cclosure_marshal_generic,
 
141
                                            G_TYPE_NONE,
 
142
                                            2,
 
143
                                            G_TYPE_BOOLEAN,
 
144
                                            G_TYPE_BOOLEAN);
 
145
}
 
146
 
 
147
static PolkitActionDescription *
 
148
get_desc_for_action (PolkitAuthority *authority,
 
149
                     const gchar     *action_id)
 
150
{
 
151
  GList *action_descs;
 
152
  GList *l;
 
153
  PolkitActionDescription *result;
 
154
 
 
155
  result = NULL;
 
156
 
 
157
  action_descs = polkit_authority_enumerate_actions_sync (authority,
 
158
                                                          NULL,
 
159
                                                          NULL);
 
160
  for (l = action_descs; l != NULL; l = l->next)
 
161
    {
 
162
      PolkitActionDescription *action_desc = POLKIT_ACTION_DESCRIPTION (l->data);
 
163
 
 
164
      if (strcmp (polkit_action_description_get_action_id (action_desc), action_id) == 0)
 
165
        {
 
166
          result = g_object_ref (action_desc);
 
167
          goto out;
 
168
        }
 
169
    }
 
170
 
 
171
 out:
 
172
 
 
173
  g_list_foreach (action_descs, (GFunc) g_object_unref, NULL);
 
174
  g_list_free (action_descs);
 
175
 
 
176
  return result;
 
177
}
 
178
 
 
179
static void
 
180
on_dialog_deleted (GtkWidget *widget,
 
181
                   GdkEvent  *event,
 
182
                   gpointer   user_data)
 
183
{
 
184
  PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
 
185
 
 
186
  polkit_gnome_authenticator_cancel (authenticator);
 
187
}
 
188
 
 
189
static void
 
190
on_user_selected (GObject    *object,
 
191
                  GParamSpec *pspec,
 
192
                  gpointer    user_data)
 
193
{
 
194
  PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
 
195
 
 
196
  /* clear any previous messages */
 
197
  polkit_gnome_authentication_dialog_set_info_message (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog), "");
 
198
 
 
199
  polkit_gnome_authenticator_cancel (authenticator);
 
200
  authenticator->new_user_selected = TRUE;
 
201
}
 
202
 
 
203
PolkitGnomeAuthenticator *
 
204
polkit_gnome_authenticator_new (const gchar     *action_id,
 
205
                                const gchar     *message,
 
206
                                const gchar     *icon_name,
 
207
                                PolkitDetails   *details,
 
208
                                const gchar     *cookie,
 
209
                                GList           *identities)
 
210
{
 
211
  PolkitGnomeAuthenticator *authenticator;
 
212
  GList *l;
 
213
  guint n;
 
214
  GError *error;
 
215
 
 
216
  authenticator = POLKIT_GNOME_AUTHENTICATOR (g_object_new (POLKIT_GNOME_TYPE_AUTHENTICATOR, NULL));
 
217
 
 
218
  error = NULL;
 
219
  authenticator->authority = polkit_authority_get_sync (NULL /* GCancellable* */, &error);
 
220
  if (authenticator->authority == NULL)
 
221
    {
 
222
      g_critical ("Error getting authority: %s", error->message);
 
223
      g_error_free (error);
 
224
      goto error;
 
225
    }
 
226
 
 
227
  authenticator->action_id = g_strdup (action_id);
 
228
  authenticator->message = g_strdup (message);
 
229
  authenticator->icon_name = g_strdup (icon_name);
 
230
  if (details != NULL)
 
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);
 
235
 
 
236
  authenticator->action_desc = get_desc_for_action (authenticator->authority,
 
237
                                                    authenticator->action_id);
 
238
  if (authenticator->action_desc == NULL)
 
239
    goto error;
 
240
 
 
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++)
 
243
    {
 
244
      PolkitUnixUser *user = POLKIT_UNIX_USER (l->data);
 
245
      uid_t uid;
 
246
      struct passwd *passwd;
 
247
 
 
248
      uid = polkit_unix_user_get_uid (user);
 
249
      passwd = getpwuid (uid);
 
250
      authenticator->users[n] = g_strdup (passwd->pw_name);
 
251
    }
 
252
 
 
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,
 
262
                    "delete-event",
 
263
                    G_CALLBACK (on_dialog_deleted),
 
264
                    authenticator);
 
265
  g_signal_connect (authenticator->dialog,
 
266
                    "notify::selected-user",
 
267
                    G_CALLBACK (on_user_selected),
 
268
                    authenticator);
 
269
 
 
270
  return authenticator;
 
271
 
 
272
 error:
 
273
  g_object_unref (authenticator);
 
274
  return NULL;
 
275
}
 
276
 
 
277
static void
 
278
session_request (PolkitAgentSession *session,
 
279
                 const char         *request,
 
280
                 gboolean            echo_on,
 
281
                 gpointer            user_data)
 
282
{
 
283
  PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
 
284
  gchar *password;
 
285
  gchar *modified_request;
 
286
 
 
287
  password = NULL;
 
288
 
 
289
  //g_debug ("in conversation_pam_prompt, request='%s', echo_on=%d", request, echo_on);
 
290
 
 
291
  /* Fix up, and localize, password prompt if it's password auth */
 
292
  if (g_ascii_strncasecmp (request, "password:", 9) == 0)
 
293
    {
 
294
      if (strcmp (g_get_user_name (), authenticator->selected_user) != 0)
 
295
        {
 
296
          modified_request = g_strdup_printf (_("_Password for %s:"), authenticator->selected_user);
 
297
        }
 
298
      else
 
299
        {
 
300
          modified_request = g_strdup (_("_Password:"));
 
301
        }
 
302
    }
 
303
  else
 
304
    {
 
305
      modified_request = g_strdup (request);
 
306
    }
 
307
 
 
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),
 
311
                                                                               modified_request,
 
312
                                                                               echo_on,
 
313
                                                                               &authenticator->was_cancelled,
 
314
                                                                               &authenticator->new_user_selected);
 
315
 
 
316
  /* cancel auth unless user provided a password */
 
317
  if (password == NULL)
 
318
    {
 
319
      polkit_gnome_authenticator_cancel (authenticator);
 
320
      goto out;
 
321
    }
 
322
  else
 
323
    {
 
324
      polkit_agent_session_response (authenticator->session, password);
 
325
      g_free (password);
 
326
    }
 
327
 
 
328
out:
 
329
  g_free (modified_request);
 
330
}
 
331
 
 
332
static void
 
333
session_show_error (PolkitAgentSession *session,
 
334
                    const gchar        *msg,
 
335
                    gpointer            user_data)
 
336
{
 
337
  PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
 
338
  gchar *s;
 
339
 
 
340
  s = g_strconcat ("<b>", msg, "</b>", NULL);
 
341
  polkit_gnome_authentication_dialog_set_info_message (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog), s);
 
342
  g_free (s);
 
343
}
 
344
 
 
345
static void
 
346
session_show_info (PolkitAgentSession *session,
 
347
                   const gchar        *msg,
 
348
                   gpointer            user_data)
 
349
{
 
350
  PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
 
351
  gchar *s;
 
352
 
 
353
  s = g_strconcat ("<b>", msg, "</b>", NULL);
 
354
  polkit_gnome_authentication_dialog_set_info_message (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog), s);
 
355
  g_free (s);
 
356
 
 
357
  gtk_widget_show_all (GTK_WIDGET (authenticator->dialog));
 
358
  gtk_window_present (GTK_WINDOW (authenticator->dialog));
 
359
}
 
360
 
 
361
 
 
362
static void
 
363
session_completed (PolkitAgentSession *session,
 
364
                   gboolean            gained_authorization,
 
365
                   gpointer            user_data)
 
366
{
 
367
  PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
 
368
 
 
369
  authenticator->gained_authorization = gained_authorization;
 
370
 
 
371
  //g_debug ("in conversation_done gained=%d", gained_authorization);
 
372
 
 
373
  g_main_loop_quit (authenticator->loop);
 
374
}
 
375
 
 
376
 
 
377
static gboolean
 
378
do_initiate (gpointer user_data)
 
379
{
 
380
  PolkitGnomeAuthenticator *authenticator = POLKIT_GNOME_AUTHENTICATOR (user_data);
 
381
  PolkitIdentity *identity;
 
382
  gint num_tries;
 
383
 
 
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)))
 
387
    {
 
388
      /* user cancelled the dialog */
 
389
      /*g_debug ("User cancelled before selecting a user");*/
 
390
      authenticator->was_cancelled = TRUE;
 
391
      goto out;
 
392
    }
 
393
 
 
394
  authenticator->loop = g_main_loop_new (NULL, TRUE);
 
395
 
 
396
  num_tries = 0;
 
397
 
 
398
 try_again:
 
399
 
 
400
  g_free (authenticator->selected_user);
 
401
  authenticator->selected_user = polkit_gnome_authentication_dialog_get_selected_user (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog));
 
402
 
 
403
  /*g_debug ("Authenticating user %s", authenticator->selected_user);*/
 
404
  identity = polkit_unix_user_new_for_name (authenticator->selected_user, NULL);
 
405
 
 
406
  authenticator->session = polkit_agent_session_new (identity, authenticator->cookie);
 
407
 
 
408
  g_object_unref (identity);
 
409
 
 
410
  g_signal_connect (authenticator->session,
 
411
                    "request",
 
412
                    G_CALLBACK (session_request),
 
413
                    authenticator);
 
414
 
 
415
  g_signal_connect (authenticator->session,
 
416
                    "show-info",
 
417
                    G_CALLBACK (session_show_info),
 
418
                    authenticator);
 
419
 
 
420
  g_signal_connect (authenticator->session,
 
421
                    "show-error",
 
422
                    G_CALLBACK (session_show_error),
 
423
                    authenticator);
 
424
 
 
425
  g_signal_connect (authenticator->session,
 
426
                    "completed",
 
427
                    G_CALLBACK (session_completed),
 
428
                    authenticator);
 
429
 
 
430
  polkit_agent_session_initiate (authenticator->session);
 
431
 
 
432
  g_main_loop_run (authenticator->loop);
 
433
 
 
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);*/
 
438
 
 
439
  if (authenticator->new_user_selected)
 
440
    {
 
441
      /*g_debug ("New user selected");*/
 
442
      authenticator->new_user_selected = FALSE;
 
443
      g_object_unref (authenticator->session);
 
444
      authenticator->session = NULL;
 
445
      goto try_again;
 
446
    }
 
447
 
 
448
  num_tries++;
 
449
 
 
450
  if (!authenticator->gained_authorization && !authenticator->was_cancelled)
 
451
    {
 
452
      if (authenticator->dialog != NULL)
 
453
        {
 
454
          gchar *s;
 
455
 
 
456
          s = g_strconcat ("<b>", _("Authentication Failure"), "</b>", NULL);
 
457
          polkit_gnome_authentication_dialog_set_info_message (
 
458
                                  POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog),
 
459
                                  s);
 
460
          g_free (s);
 
461
          gtk_widget_queue_draw (authenticator->dialog);
 
462
 
 
463
          /* shake the dialog to indicate error */
 
464
          polkit_gnome_authentication_dialog_indicate_error (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog));
 
465
 
 
466
          if (num_tries < 3)
 
467
            {
 
468
              g_object_unref (authenticator->session);
 
469
              authenticator->session = NULL;
 
470
              goto try_again;
 
471
            }
 
472
        }
 
473
    }
 
474
 
 
475
 out:
 
476
  g_signal_emit_by_name (authenticator,
 
477
                         "completed",
 
478
                         authenticator->gained_authorization,
 
479
                         authenticator->was_cancelled);
 
480
 
 
481
  g_object_unref (authenticator);
 
482
 
 
483
  return FALSE;
 
484
}
 
485
 
 
486
void
 
487
polkit_gnome_authenticator_initiate (PolkitGnomeAuthenticator *authenticator)
 
488
{
 
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));
 
491
}
 
492
 
 
493
void
 
494
polkit_gnome_authenticator_cancel (PolkitGnomeAuthenticator *authenticator)
 
495
{
 
496
  if (authenticator->dialog != NULL)
 
497
    polkit_gnome_authentication_dialog_cancel (POLKIT_GNOME_AUTHENTICATION_DIALOG (authenticator->dialog));
 
498
 
 
499
  authenticator->was_cancelled = TRUE;
 
500
 
 
501
  if (authenticator->session != NULL)
 
502
    {
 
503
      polkit_agent_session_cancel (authenticator->session);
 
504
    }
 
505
}
 
506
 
 
507
const gchar *
 
508
polkit_gnome_authenticator_get_cookie (PolkitGnomeAuthenticator *authenticator)
 
509
{
 
510
  return authenticator->cookie;
 
511
}
 
512
 
 
513