Coverage Report

Created: 2025-07-01 07:09

/src/glib/gio/gdbusauthmechanismsha1.c
Line
Count
Source (jump to first uncovered line)
1
/* GDBus - GLib D-Bus Library
2
 *
3
 * Copyright (C) 2008-2010 Red Hat, Inc.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2.1 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General
16
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17
 *
18
 * Author: David Zeuthen <davidz@redhat.com>
19
 */
20
21
#include "config.h"
22
23
#include <string.h>
24
#include <fcntl.h>
25
#include <errno.h>
26
#include <sys/types.h>
27
28
#include <glib/gstdio.h>
29
30
#ifdef G_OS_UNIX
31
#include <unistd.h>
32
#endif
33
#ifdef G_OS_WIN32
34
#include <io.h>
35
#endif
36
37
#include "gdbusauthmechanismsha1.h"
38
#include "gcredentials.h"
39
#include "gdbuserror.h"
40
#include "gioenumtypes.h"
41
#include "gioerror.h"
42
#include "gdbusprivate.h"
43
#include "glib-private.h"
44
45
#include "glibintl.h"
46
47
/*
48
 * Arbitrary timeouts for keys in the keyring.
49
 * For interoperability, these match the reference implementation, libdbus.
50
 * To make them easier to compare, their names also match libdbus
51
 * (see dbus/dbus-keyring.c).
52
 */
53
54
/*
55
 * Maximum age of a key before we create a new key to use in challenges:
56
 * 5 minutes.
57
 */
58
0
#define NEW_KEY_TIMEOUT_SECONDS (60*5)
59
60
/*
61
 * Time before we drop a key from the keyring: 7 minutes.
62
 * Authentication will succeed if it takes less than
63
 * EXPIRE_KEYS_TIMEOUT_SECONDS - NEW_KEY_TIMEOUT_SECONDS (2 minutes)
64
 * to complete.
65
 * The spec says "delete any cookies that are old (the timeout can be
66
 * fairly short)".
67
 */
68
0
#define EXPIRE_KEYS_TIMEOUT_SECONDS (NEW_KEY_TIMEOUT_SECONDS + (60*2))
69
70
/*
71
 * Maximum amount of time a key can be in the future due to clock skew
72
 * with a shared home directory: 5 minutes.
73
 * The spec says "a reasonable time in the future".
74
 */
75
0
#define MAX_TIME_TRAVEL_SECONDS (60*5)
76
77
78
struct _GDBusAuthMechanismSha1Private
79
{
80
  gboolean is_client;
81
  gboolean is_server;
82
  GDBusAuthMechanismState state;
83
  gchar *reject_reason;  /* non-NULL iff (state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED) */
84
85
  /* used on the client side */
86
  gchar *to_send;
87
88
  /* used on the server side */
89
  gchar *cookie;
90
  gchar *server_challenge;
91
};
92
93
static gint                     mechanism_get_priority              (void);
94
static const gchar             *mechanism_get_name                  (void);
95
96
static gboolean                 mechanism_is_supported              (GDBusAuthMechanism   *mechanism);
97
static gchar                   *mechanism_encode_data               (GDBusAuthMechanism   *mechanism,
98
                                                                     const gchar          *data,
99
                                                                     gsize                 data_len,
100
                                                                     gsize                *out_data_len);
101
static gchar                   *mechanism_decode_data               (GDBusAuthMechanism   *mechanism,
102
                                                                     const gchar          *data,
103
                                                                     gsize                 data_len,
104
                                                                     gsize                *out_data_len);
105
static GDBusAuthMechanismState  mechanism_server_get_state          (GDBusAuthMechanism   *mechanism);
106
static void                     mechanism_server_initiate           (GDBusAuthMechanism   *mechanism,
107
                                                                     const gchar          *initial_response,
108
                                                                     gsize                 initial_response_len);
109
static void                     mechanism_server_data_receive       (GDBusAuthMechanism   *mechanism,
110
                                                                     const gchar          *data,
111
                                                                     gsize                 data_len);
112
static gchar                   *mechanism_server_data_send          (GDBusAuthMechanism   *mechanism,
113
                                                                     gsize                *out_data_len);
114
static gchar                   *mechanism_server_get_reject_reason  (GDBusAuthMechanism   *mechanism);
115
static void                     mechanism_server_shutdown           (GDBusAuthMechanism   *mechanism);
116
static GDBusAuthMechanismState  mechanism_client_get_state          (GDBusAuthMechanism   *mechanism);
117
static gchar                   *mechanism_client_initiate           (GDBusAuthMechanism   *mechanism,
118
                                                                     gsize                *out_initial_response_len);
119
static void                     mechanism_client_data_receive       (GDBusAuthMechanism   *mechanism,
120
                                                                     const gchar          *data,
121
                                                                     gsize                 data_len);
122
static gchar                   *mechanism_client_data_send          (GDBusAuthMechanism   *mechanism,
123
                                                                     gsize                *out_data_len);
124
static void                     mechanism_client_shutdown           (GDBusAuthMechanism   *mechanism);
125
126
/* ---------------------------------------------------------------------------------------------------- */
127
128
G_DEFINE_TYPE_WITH_PRIVATE (GDBusAuthMechanismSha1, _g_dbus_auth_mechanism_sha1, G_TYPE_DBUS_AUTH_MECHANISM)
129
130
/* ---------------------------------------------------------------------------------------------------- */
131
132
static void
133
_g_dbus_auth_mechanism_sha1_finalize (GObject *object)
134
0
{
135
0
  GDBusAuthMechanismSha1 *mechanism = G_DBUS_AUTH_MECHANISM_SHA1 (object);
136
137
0
  g_free (mechanism->priv->reject_reason);
138
0
  g_free (mechanism->priv->to_send);
139
140
0
  g_free (mechanism->priv->cookie);
141
0
  g_free (mechanism->priv->server_challenge);
142
143
0
  if (G_OBJECT_CLASS (_g_dbus_auth_mechanism_sha1_parent_class)->finalize != NULL)
144
0
    G_OBJECT_CLASS (_g_dbus_auth_mechanism_sha1_parent_class)->finalize (object);
145
0
}
146
147
static void
148
_g_dbus_auth_mechanism_sha1_class_init (GDBusAuthMechanismSha1Class *klass)
149
0
{
150
0
  GObjectClass *gobject_class;
151
0
  GDBusAuthMechanismClass *mechanism_class;
152
153
0
  gobject_class = G_OBJECT_CLASS (klass);
154
0
  gobject_class->finalize = _g_dbus_auth_mechanism_sha1_finalize;
155
156
0
  mechanism_class = G_DBUS_AUTH_MECHANISM_CLASS (klass);
157
0
  mechanism_class->get_priority              = mechanism_get_priority;
158
0
  mechanism_class->get_name                  = mechanism_get_name;
159
0
  mechanism_class->is_supported              = mechanism_is_supported;
160
0
  mechanism_class->encode_data               = mechanism_encode_data;
161
0
  mechanism_class->decode_data               = mechanism_decode_data;
162
0
  mechanism_class->server_get_state          = mechanism_server_get_state;
163
0
  mechanism_class->server_initiate           = mechanism_server_initiate;
164
0
  mechanism_class->server_data_receive       = mechanism_server_data_receive;
165
0
  mechanism_class->server_data_send          = mechanism_server_data_send;
166
0
  mechanism_class->server_get_reject_reason  = mechanism_server_get_reject_reason;
167
0
  mechanism_class->server_shutdown           = mechanism_server_shutdown;
168
0
  mechanism_class->client_get_state          = mechanism_client_get_state;
169
0
  mechanism_class->client_initiate           = mechanism_client_initiate;
170
0
  mechanism_class->client_data_receive       = mechanism_client_data_receive;
171
0
  mechanism_class->client_data_send          = mechanism_client_data_send;
172
0
  mechanism_class->client_shutdown           = mechanism_client_shutdown;
173
0
}
174
175
static void
176
_g_dbus_auth_mechanism_sha1_init (GDBusAuthMechanismSha1 *mechanism)
177
0
{
178
0
  mechanism->priv = _g_dbus_auth_mechanism_sha1_get_instance_private (mechanism);
179
0
}
180
181
/* ---------------------------------------------------------------------------------------------------- */
182
183
static gint
184
mechanism_get_priority (void)
185
0
{
186
0
  return 0;
187
0
}
188
189
static const gchar *
190
mechanism_get_name (void)
191
0
{
192
0
  return "DBUS_COOKIE_SHA1";
193
0
}
194
195
static gboolean
196
mechanism_is_supported (GDBusAuthMechanism *mechanism)
197
0
{
198
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), FALSE);
199
0
  return TRUE;
200
0
}
201
202
static gchar *
203
mechanism_encode_data (GDBusAuthMechanism   *mechanism,
204
                       const gchar          *data,
205
                       gsize                 data_len,
206
                       gsize                *out_data_len)
207
0
{
208
0
  return NULL;
209
0
}
210
211
212
static gchar *
213
mechanism_decode_data (GDBusAuthMechanism   *mechanism,
214
                       const gchar          *data,
215
                       gsize                 data_len,
216
                       gsize                *out_data_len)
217
0
{
218
0
  return NULL;
219
0
}
220
221
/* ---------------------------------------------------------------------------------------------------- */
222
223
static gint
224
random_ascii (void)
225
0
{
226
0
  gint ret;
227
0
  ret = g_random_int_range (0, 60);
228
0
  if (ret < 25)
229
0
    ret += 'A';
230
0
  else if (ret < 50)
231
0
    ret += 'a' - 25;
232
0
  else
233
0
    ret += '0' - 50;
234
0
  return ret;
235
0
}
236
237
static gchar *
238
random_ascii_string (guint len)
239
0
{
240
0
  GString *challenge;
241
0
  guint n;
242
243
0
  challenge = g_string_new (NULL);
244
0
  for (n = 0; n < len; n++)
245
0
    g_string_append_c (challenge, random_ascii ());
246
0
  return g_string_free (challenge, FALSE);
247
0
}
248
249
static gchar *
250
random_blob (guint len)
251
0
{
252
0
  GString *challenge;
253
0
  guint n;
254
255
0
  challenge = g_string_new (NULL);
256
0
  for (n = 0; n < len; n++)
257
0
    g_string_append_c (challenge, g_random_int_range (0, 256));
258
0
  return g_string_free (challenge, FALSE);
259
0
}
260
261
/* ---------------------------------------------------------------------------------------------------- */
262
263
/* ensure keyring dir exists and permissions are correct */
264
static gchar *
265
ensure_keyring_directory (GError **error)
266
0
{
267
0
  gchar *path;
268
0
  const gchar *e;
269
0
  gboolean is_setuid;
270
0
#ifdef G_OS_UNIX
271
0
  struct stat statbuf;
272
0
#endif
273
274
0
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
275
276
0
  e = g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR");
277
0
  if (e != NULL)
278
0
    {
279
0
      path = g_strdup (e);
280
0
    }
281
0
  else
282
0
    {
283
0
      path = g_build_filename (g_get_home_dir (),
284
0
                               ".dbus-keyrings",
285
0
                               NULL);
286
0
    }
287
288
0
#ifdef G_OS_UNIX
289
0
  if (stat (path, &statbuf) != 0)
290
0
    {
291
0
      int errsv = errno;
292
293
0
      if (errsv != ENOENT)
294
0
        {
295
0
          g_set_error (error,
296
0
                       G_IO_ERROR,
297
0
                       g_io_error_from_errno (errsv),
298
0
                       _("Error when getting information for directory ā€œ%sā€: %s"),
299
0
                       path,
300
0
                       g_strerror (errsv));
301
0
          g_clear_pointer (&path, g_free);
302
0
          return NULL;
303
0
        }
304
0
    }
305
0
  else if (S_ISDIR (statbuf.st_mode))
306
0
    {
307
0
      if (g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION") == NULL &&
308
0
          (statbuf.st_mode & 0777) != 0700)
309
0
        {
310
0
          g_set_error (error,
311
0
                       G_IO_ERROR,
312
0
                       G_IO_ERROR_FAILED,
313
0
                       _("Permissions on directory ā€œ%sā€ are malformed. Expected mode 0700, got 0%o"),
314
0
                       path,
315
0
                       (guint) (statbuf.st_mode & 0777));
316
0
          g_clear_pointer (&path, g_free);
317
0
          return NULL;
318
0
        }
319
320
0
      return g_steal_pointer (&path);
321
0
    }
322
#else  /* if !G_OS_UNIX */
323
  /* On non-Unix platforms, check that it exists as a directory, but don’t do
324
   * permissions checks at the moment. */
325
  if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
326
    {
327
#ifdef __GNUC__
328
#pragma GCC diagnostic push
329
#pragma GCC diagnostic warning "-Wcpp"
330
#warning Please implement permission checking on this non-UNIX platform
331
#pragma GCC diagnostic pop
332
#endif  /* __GNUC__ */
333
      return g_steal_pointer (&path);
334
    }
335
#endif  /* if !G_OS_UNIX */
336
337
  /* Only create the directory if not running as setuid */
338
0
  is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) ();
339
0
  if (!is_setuid &&
340
0
      g_mkdir_with_parents (path, 0700) != 0)
341
0
    {
342
0
      int errsv = errno;
343
0
      g_set_error (error,
344
0
                   G_IO_ERROR,
345
0
                   g_io_error_from_errno (errsv),
346
0
                   _("Error creating directory ā€œ%sā€: %s"),
347
0
                   path,
348
0
                   g_strerror (errsv));
349
0
      g_clear_pointer (&path, g_free);
350
0
      return NULL;
351
0
    }
352
0
  else if (is_setuid)
353
0
    {
354
0
      g_set_error (error,
355
0
                   G_IO_ERROR,
356
0
                   G_IO_ERROR_PERMISSION_DENIED,
357
0
                   _("Error creating directory ā€œ%sā€: %s"),
358
0
                   path,
359
0
                   _("Operation not supported"));
360
0
      g_clear_pointer (&path, g_free);
361
0
      return NULL;
362
0
    }
363
364
0
  return g_steal_pointer (&path);
365
0
}
366
367
/* ---------------------------------------------------------------------------------------------------- */
368
369
/* looks up an entry in the keyring */
370
static gchar *
371
keyring_lookup_entry (const gchar  *cookie_context,
372
                      gint          cookie_id,
373
                      GError      **error)
374
0
{
375
0
  gchar *ret;
376
0
  gchar *keyring_dir;
377
0
  gchar *contents;
378
0
  gchar *path;
379
0
  guint n;
380
0
  gchar **lines;
381
382
0
  g_return_val_if_fail (cookie_context != NULL, NULL);
383
0
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
384
385
0
  ret = NULL;
386
0
  path = NULL;
387
0
  contents = NULL;
388
0
  lines = NULL;
389
390
0
  keyring_dir = ensure_keyring_directory (error);
391
0
  if (keyring_dir == NULL)
392
0
    goto out;
393
394
0
  path = g_build_filename (keyring_dir, cookie_context, NULL);
395
396
0
  if (!g_file_get_contents (path,
397
0
                            &contents,
398
0
                            NULL,
399
0
                            error))
400
0
    {
401
0
      g_prefix_error (error,
402
0
                      _("Error opening keyring ā€œ%sā€ for reading: "),
403
0
                      path);
404
0
      goto out;
405
0
    }
406
0
  g_assert (contents != NULL);
407
408
0
  lines = g_strsplit (contents, "\n", 0);
409
0
  for (n = 0; lines[n] != NULL; n++)
410
0
    {
411
0
      const gchar *line = lines[n];
412
0
      gchar **tokens;
413
0
      gchar *endp;
414
0
      gint line_id;
415
416
0
      if (line[0] == '\0')
417
0
        continue;
418
419
0
      tokens = g_strsplit (line, " ", 0);
420
0
      if (g_strv_length (tokens) != 3)
421
0
        {
422
0
          g_set_error (error,
423
0
                       G_IO_ERROR,
424
0
                       G_IO_ERROR_FAILED,
425
0
                       _("Line %d of the keyring at ā€œ%sā€ with content ā€œ%sā€ is malformed"),
426
0
                       n + 1,
427
0
                       path,
428
0
                       line);
429
0
          g_strfreev (tokens);
430
0
          goto out;
431
0
        }
432
433
0
      line_id = g_ascii_strtoll (tokens[0], &endp, 10);
434
0
      if (*endp != '\0')
435
0
        {
436
0
          g_set_error (error,
437
0
                       G_IO_ERROR,
438
0
                       G_IO_ERROR_FAILED,
439
0
                       _("First token of line %d of the keyring at ā€œ%sā€ with content ā€œ%sā€ is malformed"),
440
0
                       n + 1,
441
0
                       path,
442
0
                       line);
443
0
          g_strfreev (tokens);
444
0
          goto out;
445
0
        }
446
447
0
      (void)g_ascii_strtoll (tokens[1], &endp, 10); /* do not care what the timestamp is */
448
0
      if (*endp != '\0')
449
0
        {
450
0
          g_set_error (error,
451
0
                       G_IO_ERROR,
452
0
                       G_IO_ERROR_FAILED,
453
0
                       _("Second token of line %d of the keyring at ā€œ%sā€ with content ā€œ%sā€ is malformed"),
454
0
                       n + 1,
455
0
                       path,
456
0
                       line);
457
0
          g_strfreev (tokens);
458
0
          goto out;
459
0
        }
460
461
0
      if (line_id == cookie_id)
462
0
        {
463
          /* YAY, success */
464
0
          ret = tokens[2]; /* steal pointer */
465
0
          tokens[2] = NULL;
466
0
          g_strfreev (tokens);
467
0
          goto out;
468
0
        }
469
470
0
      g_strfreev (tokens);
471
0
    }
472
473
  /* BOOH, didn't find the cookie */
474
0
  g_set_error (error,
475
0
               G_IO_ERROR,
476
0
               G_IO_ERROR_FAILED,
477
0
               _("Didn’t find cookie with id %d in the keyring at ā€œ%sā€"),
478
0
               cookie_id,
479
0
               path);
480
481
0
 out:
482
0
  g_free (keyring_dir);
483
0
  g_free (path);
484
0
  g_free (contents);
485
0
  g_strfreev (lines);
486
0
  return ret;
487
0
}
488
489
/* function for logging important events that the system administrator should take notice of */
490
G_GNUC_PRINTF(1, 2)
491
static void
492
_log (const gchar *message,
493
      ...)
494
0
{
495
0
  gchar *s;
496
0
  va_list var_args;
497
498
0
  va_start (var_args, message);
499
0
  s = g_strdup_vprintf (message, var_args);
500
0
  va_end (var_args);
501
502
  /* TODO: might want to send this to syslog instead */
503
0
  g_printerr ("GDBus-DBUS_COOKIE_SHA1: %s\n", s);
504
0
  g_free (s);
505
0
}
506
507
/* Returns FD for lock file, if it was created exclusively (didn't exist already,
508
 * and was created successfully) */
509
static gint
510
create_lock_exclusive (const gchar  *lock_path,
511
                       GError      **error)
512
0
{
513
0
  int errsv;
514
0
  gint ret;
515
516
0
  ret = g_open (lock_path, O_CREAT | O_EXCL, 0600);
517
0
  errsv = errno;
518
0
  if (ret < 0)
519
0
    {
520
0
      g_set_error (error,
521
0
                   G_IO_ERROR,
522
0
                   g_io_error_from_errno (errsv),
523
0
                   _("Error creating lock file ā€œ%sā€: %s"),
524
0
                   lock_path,
525
0
                   g_strerror (errsv));
526
0
      return -1;
527
0
    }
528
529
0
  return ret;
530
0
}
531
532
static gint
533
keyring_acquire_lock (const gchar  *path,
534
                      GError      **error)
535
0
{
536
0
  gchar *lock = NULL;
537
0
  gint ret;
538
0
  guint num_tries;
539
0
  int errsv;
540
541
  /* Total possible sleep period = max_tries * timeout_usec = 0.5s */
542
0
  const guint max_tries = 50;
543
0
  const guint timeout_usec = 1000 * 10;
544
545
0
  g_return_val_if_fail (path != NULL, -1);
546
0
  g_return_val_if_fail (error == NULL || *error == NULL, -1);
547
548
0
  ret = -1;
549
0
  lock = g_strconcat (path, ".lock", NULL);
550
551
  /* This is what the D-Bus spec says
552
   * (https://dbus.freedesktop.org/doc/dbus-specification.html#auth-mechanisms-sha)
553
   *
554
   *  Create a lockfile name by appending ".lock" to the name of the
555
   *  cookie file. The server should attempt to create this file using
556
   *  O_CREAT | O_EXCL. If file creation fails, the lock
557
   *  fails. Servers should retry for a reasonable period of time,
558
   *  then they may choose to delete an existing lock to keep users
559
   *  from having to manually delete a stale lock. [1]
560
   *
561
   *  [1] : Lockfiles are used instead of real file locking fcntl() because
562
   *         real locking implementations are still flaky on network filesystems
563
   */
564
565
0
  for (num_tries = 0; num_tries < max_tries; num_tries++)
566
0
    {
567
      /* Ignore the error until the final call. */
568
0
      ret = create_lock_exclusive (lock, NULL);
569
0
      if (ret >= 0)
570
0
        break;
571
572
      /* sleep 10ms, then try again */
573
0
      g_usleep (timeout_usec);
574
0
    }
575
576
0
  if (num_tries == max_tries)
577
0
    {
578
      /* ok, we slept 50*10ms = 0.5 seconds. Conclude that the lock file must be
579
       * stale (nuke it from orbit)
580
       */
581
0
      if (g_unlink (lock) != 0)
582
0
        {
583
0
          errsv = errno;
584
0
          g_set_error (error,
585
0
                       G_IO_ERROR,
586
0
                       g_io_error_from_errno (errsv),
587
0
                       _("Error deleting stale lock file ā€œ%sā€: %s"),
588
0
                       lock,
589
0
                       g_strerror (errsv));
590
0
          goto out;
591
0
        }
592
593
0
      _log ("Deleted stale lock file '%s'", lock);
594
595
      /* Try one last time to create it, now that we've deleted the stale one */
596
0
      ret = create_lock_exclusive (lock, error);
597
0
      if (ret < 0)
598
0
        goto out;
599
0
    }
600
601
0
out:
602
0
  g_free (lock);
603
0
  return ret;
604
0
}
605
606
static gboolean
607
keyring_release_lock (const gchar  *path,
608
                      gint          lock_fd,
609
                      GError      **error)
610
0
{
611
0
  gchar *lock;
612
0
  gboolean ret;
613
614
0
  g_return_val_if_fail (path != NULL, FALSE);
615
0
  g_return_val_if_fail (lock_fd != -1, FALSE);
616
0
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
617
618
0
  ret = FALSE;
619
0
  lock = g_strdup_printf ("%s.lock", path);
620
0
  if (close (lock_fd) != 0)
621
0
    {
622
0
      int errsv = errno;
623
0
      g_set_error (error,
624
0
                   G_IO_ERROR,
625
0
                   g_io_error_from_errno (errsv),
626
0
                   _("Error closing (unlinked) lock file ā€œ%sā€: %s"),
627
0
                   lock,
628
0
                   g_strerror (errsv));
629
0
      goto out;
630
0
    }
631
0
  if (g_unlink (lock) != 0)
632
0
    {
633
0
      int errsv = errno;
634
0
      g_set_error (error,
635
0
                   G_IO_ERROR,
636
0
                   g_io_error_from_errno (errsv),
637
0
                   _("Error unlinking lock file ā€œ%sā€: %s"),
638
0
                   lock,
639
0
                   g_strerror (errsv));
640
0
      goto out;
641
0
    }
642
643
0
  ret = TRUE;
644
645
0
 out:
646
0
  g_free (lock);
647
0
  return ret;
648
0
}
649
650
651
/* adds an entry to the keyring, taking care of locking and deleting stale/future entries */
652
static gboolean
653
keyring_generate_entry (const gchar  *cookie_context,
654
                        gint         *out_id,
655
                        gchar       **out_cookie,
656
                        GError      **error)
657
0
{
658
0
  gboolean ret;
659
0
  gchar *keyring_dir;
660
0
  gchar *path;
661
0
  gchar *contents;
662
0
  GError *local_error;
663
0
  gchar **lines;
664
0
  gint max_line_id;
665
0
  GString *new_contents;
666
0
  gint64 now;
667
0
  gboolean have_id;
668
0
  gint use_id;
669
0
  gchar *use_cookie;
670
0
  gboolean changed_file;
671
0
  gint lock_fd;
672
673
0
  g_return_val_if_fail (cookie_context != NULL, FALSE);
674
0
  g_return_val_if_fail (out_id != NULL, FALSE);
675
0
  g_return_val_if_fail (out_cookie != NULL, FALSE);
676
0
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
677
678
0
  ret = FALSE;
679
0
  path = NULL;
680
0
  contents = NULL;
681
0
  lines = NULL;
682
0
  new_contents = NULL;
683
0
  have_id = FALSE;
684
0
  use_id = 0;
685
0
  use_cookie = NULL;
686
0
  lock_fd = -1;
687
688
0
  keyring_dir = ensure_keyring_directory (error);
689
0
  if (keyring_dir == NULL)
690
0
    goto out;
691
692
0
  path = g_build_filename (keyring_dir, cookie_context, NULL);
693
694
0
  lock_fd = keyring_acquire_lock (path, error);
695
0
  if (lock_fd == -1)
696
0
    goto out;
697
698
0
  local_error = NULL;
699
0
  contents = NULL;
700
0
  if (!g_file_get_contents (path,
701
0
                            &contents,
702
0
                            NULL,
703
0
                            &local_error))
704
0
    {
705
0
      if (local_error->domain == G_FILE_ERROR && local_error->code == G_FILE_ERROR_NOENT)
706
0
        {
707
          /* file doesn't have to exist */
708
0
          g_error_free (local_error);
709
0
        }
710
0
      else
711
0
        {
712
0
          g_propagate_prefixed_error (error,
713
0
                                      local_error,
714
0
                                      _("Error opening keyring ā€œ%sā€ for writing: "),
715
0
                                      path);
716
0
          goto out;
717
0
        }
718
0
    }
719
720
0
  new_contents = g_string_new (NULL);
721
0
  now = g_get_real_time () / G_USEC_PER_SEC;
722
0
  changed_file = FALSE;
723
724
0
  max_line_id = 0;
725
0
  if (contents != NULL)
726
0
    {
727
0
      guint n;
728
0
      lines = g_strsplit (contents, "\n", 0);
729
0
      for (n = 0; lines[n] != NULL; n++)
730
0
        {
731
0
          const gchar *line = lines[n];
732
0
          gchar **tokens;
733
0
          gchar *endp;
734
0
          gint line_id;
735
0
          gint64 line_when;
736
0
          gboolean keep_entry;
737
738
0
          if (line[0] == '\0')
739
0
            continue;
740
741
0
          tokens = g_strsplit (line, " ", 0);
742
0
          if (g_strv_length (tokens) != 3)
743
0
            {
744
0
              g_set_error (error,
745
0
                           G_IO_ERROR,
746
0
                           G_IO_ERROR_FAILED,
747
0
                           _("Line %d of the keyring at ā€œ%sā€ with content ā€œ%sā€ is malformed"),
748
0
                           n + 1,
749
0
                           path,
750
0
                           line);
751
0
              g_strfreev (tokens);
752
0
              goto out;
753
0
            }
754
755
0
          line_id = g_ascii_strtoll (tokens[0], &endp, 10);
756
0
          if (*endp != '\0')
757
0
            {
758
0
              g_set_error (error,
759
0
                           G_IO_ERROR,
760
0
                           G_IO_ERROR_FAILED,
761
0
                           _("First token of line %d of the keyring at ā€œ%sā€ with content ā€œ%sā€ is malformed"),
762
0
                           n + 1,
763
0
                           path,
764
0
                           line);
765
0
              g_strfreev (tokens);
766
0
              goto out;
767
0
            }
768
769
0
          line_when = g_ascii_strtoll (tokens[1], &endp, 10);
770
0
          if (*endp != '\0')
771
0
            {
772
0
              g_set_error (error,
773
0
                           G_IO_ERROR,
774
0
                           G_IO_ERROR_FAILED,
775
0
                           _("Second token of line %d of the keyring at ā€œ%sā€ with content ā€œ%sā€ is malformed"),
776
0
                           n + 1,
777
0
                           path,
778
0
                           line);
779
0
              g_strfreev (tokens);
780
0
              goto out;
781
0
            }
782
783
784
          /* D-Bus spec says:
785
           *
786
           *  Once the lockfile has been created, the server loads the
787
           *  cookie file. It should then delete any cookies that are
788
           *  old (the timeout can be fairly short), or more than a
789
           *  reasonable time in the future (so that cookies never
790
           *  accidentally become permanent, if the clock was set far
791
           *  into the future at some point). If no recent keys remain,
792
           *  the server may generate a new key.
793
           *
794
           */
795
0
          keep_entry = TRUE;
796
0
          if (line_when > now)
797
0
            {
798
              /* Oddball case: entry is more recent than our current wall-clock time..
799
               * This is OK, it means that another server on another machine but with
800
               * same $HOME wrote the entry. */
801
0
              if (line_when - now > MAX_TIME_TRAVEL_SECONDS)
802
0
                {
803
0
                  keep_entry = FALSE;
804
0
                  _log ("Deleted SHA1 cookie from %" G_GUINT64_FORMAT " seconds in the future", line_when - now);
805
0
                }
806
0
            }
807
0
          else
808
0
            {
809
              /* Discard entry if it's too old. */
810
0
              if (now - line_when > EXPIRE_KEYS_TIMEOUT_SECONDS)
811
0
                {
812
0
                  keep_entry = FALSE;
813
0
                }
814
0
            }
815
816
0
          if (!keep_entry)
817
0
            {
818
0
              changed_file = FALSE;
819
0
            }
820
0
          else
821
0
            {
822
0
              g_string_append_printf (new_contents,
823
0
                                      "%d %" G_GUINT64_FORMAT " %s\n",
824
0
                                      line_id,
825
0
                                      line_when,
826
0
                                      tokens[2]);
827
0
              max_line_id = MAX (line_id, max_line_id);
828
              /* Only reuse entry if not older than 5 minutes.
829
               *
830
               * (We need a bit of grace time compared to 7 minutes above.. otherwise
831
               * there's a race where we reuse the 6min59.9 secs old entry and a
832
               * split-second later another server purges the now 7 minute old entry.)
833
               */
834
0
              if (now - line_when < NEW_KEY_TIMEOUT_SECONDS)
835
0
                {
836
0
                  if (!have_id)
837
0
                    {
838
0
                      use_id = line_id;
839
0
                      use_cookie = tokens[2]; /* steal memory */
840
0
                      tokens[2] = NULL;
841
0
                      have_id = TRUE;
842
0
                    }
843
0
                }
844
0
            }
845
0
          g_strfreev (tokens);
846
0
        }
847
0
    } /* for each line */
848
849
0
  ret = TRUE;
850
851
0
  if (have_id)
852
0
    {
853
0
      *out_id = use_id;
854
0
      *out_cookie = use_cookie;
855
0
      use_cookie = NULL;
856
0
    }
857
0
  else
858
0
    {
859
0
      gchar *raw_cookie;
860
0
      *out_id = max_line_id + 1;
861
0
      raw_cookie = random_blob (32);
862
0
      *out_cookie = _g_dbus_hexencode (raw_cookie, 32);
863
0
      g_free (raw_cookie);
864
865
0
      g_string_append_printf (new_contents,
866
0
                              "%d %" G_GINT64_FORMAT " %s\n",
867
0
                              *out_id,
868
0
                              g_get_real_time () / G_USEC_PER_SEC,
869
0
                              *out_cookie);
870
0
      changed_file = TRUE;
871
0
    }
872
873
  /* and now actually write the cookie file if there are changes (this is atomic) */
874
0
  if (changed_file)
875
0
    {
876
0
      if (!g_file_set_contents_full (path,
877
0
                                     new_contents->str,
878
0
                                     -1,
879
0
                                     G_FILE_SET_CONTENTS_CONSISTENT,
880
0
                                     0600,
881
0
                                     error))
882
0
        {
883
0
          *out_id = 0;
884
0
          *out_cookie = 0;
885
0
          g_free (*out_cookie);
886
0
          ret = FALSE;
887
0
          goto out;
888
0
        }
889
0
    }
890
891
0
 out:
892
893
0
  if (lock_fd != -1)
894
0
    {
895
0
      GError *local_error;
896
0
      local_error = NULL;
897
0
      if (!keyring_release_lock (path, lock_fd, &local_error))
898
0
        {
899
0
          if (error != NULL)
900
0
            {
901
0
              if (*error == NULL)
902
0
                {
903
0
                  *error = local_error;
904
0
                }
905
0
              else
906
0
                {
907
0
                  g_prefix_error (error,
908
0
                                  _("(Additionally, releasing the lock for ā€œ%sā€ also failed: %s) "),
909
0
                                  path,
910
0
                                  local_error->message);
911
0
                }
912
0
            }
913
0
          else
914
0
            {
915
0
              g_error_free (local_error);
916
0
            }
917
0
        }
918
0
    }
919
920
0
  g_free (keyring_dir);
921
0
  g_free (path);
922
0
  g_strfreev (lines);
923
0
  g_free (contents);
924
0
  if (new_contents != NULL)
925
0
    g_string_free (new_contents, TRUE);
926
0
  g_free (use_cookie);
927
0
  return ret;
928
0
}
929
930
/* ---------------------------------------------------------------------------------------------------- */
931
932
static gchar *
933
generate_sha1 (const gchar *server_challenge,
934
               const gchar *client_challenge,
935
               const gchar *cookie)
936
0
{
937
0
  GString *str;
938
0
  gchar *sha1;
939
940
0
  str = g_string_new (server_challenge);
941
0
  g_string_append_c (str, ':');
942
0
  g_string_append (str, client_challenge);
943
0
  g_string_append_c (str, ':');
944
0
  g_string_append (str, cookie);
945
0
  sha1 = g_compute_checksum_for_string (G_CHECKSUM_SHA1, str->str, -1);
946
0
  g_string_free (str, TRUE);
947
948
0
  return sha1;
949
0
}
950
951
/* ---------------------------------------------------------------------------------------------------- */
952
953
static GDBusAuthMechanismState
954
mechanism_server_get_state (GDBusAuthMechanism   *mechanism)
955
0
{
956
0
  GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
957
958
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
959
0
  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
960
961
0
  return m->priv->state;
962
0
}
963
964
static void
965
mechanism_server_initiate (GDBusAuthMechanism   *mechanism,
966
                           const gchar          *initial_response,
967
                           gsize                 initial_response_len)
968
0
{
969
0
  GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
970
971
0
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
972
0
  g_return_if_fail (!m->priv->is_server && !m->priv->is_client);
973
974
0
  m->priv->is_server = TRUE;
975
0
  m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
976
977
0
  if (initial_response != NULL && initial_response_len > 0)
978
0
    {
979
0
#ifdef G_OS_UNIX
980
0
      gint64 uid;
981
0
      gchar *endp;
982
983
0
      uid = g_ascii_strtoll (initial_response, &endp, 10);
984
0
      if (*endp == '\0')
985
0
        {
986
0
          if (uid == getuid ())
987
0
            {
988
0
              m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
989
0
            }
990
0
        }
991
#elif defined(G_OS_WIN32)
992
      gchar *sid;
993
      sid = _g_dbus_win32_get_user_sid ();
994
      if (g_strcmp0 (initial_response, sid) == 0)
995
        m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
996
      g_free (sid);
997
#else
998
#error Please implement for your OS
999
#endif
1000
0
    }
1001
0
}
1002
1003
static void
1004
mechanism_server_data_receive (GDBusAuthMechanism   *mechanism,
1005
                               const gchar          *data,
1006
                               gsize                 data_len)
1007
0
{
1008
0
  GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1009
0
  gchar **tokens;
1010
0
  const gchar *client_challenge;
1011
0
  const gchar *alleged_sha1;
1012
0
  gchar *sha1;
1013
1014
0
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1015
0
  g_return_if_fail (m->priv->is_server && !m->priv->is_client);
1016
0
  g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
1017
1018
0
  tokens = NULL;
1019
0
  sha1 = NULL;
1020
1021
0
  tokens = g_strsplit (data, " ", 0);
1022
0
  if (g_strv_length (tokens) != 2)
1023
0
    {
1024
0
      g_free (m->priv->reject_reason);
1025
0
      m->priv->reject_reason = g_strdup_printf ("Malformed data '%s'", data);
1026
0
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1027
0
      goto out;
1028
0
    }
1029
1030
0
  client_challenge = tokens[0];
1031
0
  alleged_sha1 = tokens[1];
1032
1033
0
  sha1 = generate_sha1 (m->priv->server_challenge, client_challenge, m->priv->cookie);
1034
1035
0
  if (g_strcmp0 (sha1, alleged_sha1) == 0)
1036
0
    {
1037
0
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
1038
0
    }
1039
0
  else
1040
0
    {
1041
0
      g_free (m->priv->reject_reason);
1042
0
      m->priv->reject_reason = g_strdup_printf ("SHA-1 mismatch");
1043
0
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1044
0
    }
1045
1046
0
 out:
1047
0
  g_strfreev (tokens);
1048
0
  g_free (sha1);
1049
0
}
1050
1051
static gchar *
1052
mechanism_server_data_send (GDBusAuthMechanism   *mechanism,
1053
                            gsize                *out_data_len)
1054
0
{
1055
0
  GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1056
0
  gchar *s;
1057
0
  gint cookie_id;
1058
0
  const gchar *cookie_context;
1059
0
  GError *error;
1060
1061
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1062
0
  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
1063
0
  g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
1064
1065
0
  s = NULL;
1066
0
  *out_data_len = 0;
1067
1068
  /* TODO: use GDBusAuthObserver here to get the cookie context to use? */
1069
0
  cookie_context = "org_gtk_gdbus_general";
1070
1071
0
  cookie_id = -1;
1072
0
  error = NULL;
1073
0
  if (!keyring_generate_entry (cookie_context,
1074
0
                               &cookie_id,
1075
0
                               &m->priv->cookie,
1076
0
                               &error))
1077
0
    {
1078
0
      g_free (m->priv->reject_reason);
1079
0
      m->priv->reject_reason = g_strdup_printf ("Error adding entry to keyring: %s", error->message);
1080
0
      g_error_free (error);
1081
0
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1082
0
      goto out;
1083
0
    }
1084
1085
0
  m->priv->server_challenge = random_ascii_string (16);
1086
0
  s = g_strdup_printf ("%s %d %s",
1087
0
                       cookie_context,
1088
0
                       cookie_id,
1089
0
                       m->priv->server_challenge);
1090
0
  *out_data_len = strlen (s);
1091
1092
0
  m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
1093
1094
0
 out:
1095
0
  return s;
1096
0
}
1097
1098
static gchar *
1099
mechanism_server_get_reject_reason (GDBusAuthMechanism   *mechanism)
1100
0
{
1101
0
  GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1102
1103
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1104
0
  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
1105
0
  g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
1106
1107
0
  return g_strdup (m->priv->reject_reason);
1108
0
}
1109
1110
static void
1111
mechanism_server_shutdown (GDBusAuthMechanism   *mechanism)
1112
0
{
1113
0
  GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1114
1115
0
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1116
0
  g_return_if_fail (m->priv->is_server && !m->priv->is_client);
1117
1118
0
  m->priv->is_server = FALSE;
1119
0
}
1120
1121
/* ---------------------------------------------------------------------------------------------------- */
1122
1123
static GDBusAuthMechanismState
1124
mechanism_client_get_state (GDBusAuthMechanism   *mechanism)
1125
0
{
1126
0
  GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1127
1128
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
1129
0
  g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
1130
1131
0
  return m->priv->state;
1132
0
}
1133
1134
static gchar *
1135
mechanism_client_initiate (GDBusAuthMechanism   *mechanism,
1136
                           gsize                *out_initial_response_len)
1137
0
{
1138
0
  GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1139
0
  gchar *initial_response;
1140
1141
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1142
0
  g_return_val_if_fail (!m->priv->is_server && !m->priv->is_client, NULL);
1143
1144
0
  m->priv->is_client = TRUE;
1145
0
  m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
1146
1147
0
  *out_initial_response_len = 0;
1148
1149
0
#ifdef G_OS_UNIX
1150
0
  initial_response = g_strdup_printf ("%" G_GINT64_FORMAT, (gint64) getuid ());
1151
0
  *out_initial_response_len = strlen (initial_response);
1152
#elif defined (G_OS_WIN32)
1153
  initial_response = _g_dbus_win32_get_user_sid ();
1154
  *out_initial_response_len = strlen (initial_response);
1155
#else
1156
#error Please implement for your OS
1157
#endif
1158
0
  g_assert (initial_response != NULL);
1159
1160
0
  return initial_response;
1161
0
}
1162
1163
static void
1164
mechanism_client_data_receive (GDBusAuthMechanism   *mechanism,
1165
                               const gchar          *data,
1166
                               gsize                 data_len)
1167
0
{
1168
0
  GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1169
0
  gchar **tokens;
1170
0
  const gchar *cookie_context;
1171
0
  guint cookie_id;
1172
0
  const gchar *server_challenge;
1173
0
  gchar *client_challenge;
1174
0
  gchar *endp;
1175
0
  gchar *cookie;
1176
0
  GError *error;
1177
0
  gchar *sha1;
1178
1179
0
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1180
0
  g_return_if_fail (m->priv->is_client && !m->priv->is_server);
1181
0
  g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
1182
1183
0
  tokens = NULL;
1184
0
  cookie = NULL;
1185
0
  client_challenge = NULL;
1186
1187
0
  tokens = g_strsplit (data, " ", 0);
1188
0
  if (g_strv_length (tokens) != 3)
1189
0
    {
1190
0
      g_free (m->priv->reject_reason);
1191
0
      m->priv->reject_reason = g_strdup_printf ("Malformed data '%s'", data);
1192
0
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1193
0
      goto out;
1194
0
    }
1195
1196
0
  cookie_context = tokens[0];
1197
0
  cookie_id = g_ascii_strtoll (tokens[1], &endp, 10);
1198
0
  if (*endp != '\0')
1199
0
    {
1200
0
      g_free (m->priv->reject_reason);
1201
0
      m->priv->reject_reason = g_strdup_printf ("Malformed cookie_id '%s'", tokens[1]);
1202
0
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1203
0
      goto out;
1204
0
    }
1205
0
  server_challenge = tokens[2];
1206
1207
0
  error = NULL;
1208
0
  cookie = keyring_lookup_entry (cookie_context, cookie_id, &error);
1209
0
  if (cookie == NULL)
1210
0
    {
1211
0
      g_free (m->priv->reject_reason);
1212
0
      m->priv->reject_reason = g_strdup_printf ("Problems looking up entry in keyring: %s", error->message);
1213
0
      g_error_free (error);
1214
0
      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1215
0
      goto out;
1216
0
    }
1217
1218
0
  client_challenge = random_ascii_string (16);
1219
0
  sha1 = generate_sha1 (server_challenge, client_challenge, cookie);
1220
0
  m->priv->to_send = g_strdup_printf ("%s %s", client_challenge, sha1);
1221
0
  g_free (sha1);
1222
0
  m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
1223
1224
0
 out:
1225
0
  g_strfreev (tokens);
1226
0
  g_free (cookie);
1227
0
  g_free (client_challenge);
1228
0
}
1229
1230
static gchar *
1231
mechanism_client_data_send (GDBusAuthMechanism   *mechanism,
1232
                            gsize                *out_data_len)
1233
0
{
1234
0
  GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1235
1236
0
  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1237
0
  g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, NULL);
1238
0
  g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
1239
1240
0
  g_assert (m->priv->to_send != NULL);
1241
1242
0
  m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
1243
1244
0
  *out_data_len = strlen (m->priv->to_send);
1245
0
  return g_strdup (m->priv->to_send);
1246
0
}
1247
1248
static void
1249
mechanism_client_shutdown (GDBusAuthMechanism   *mechanism)
1250
0
{
1251
0
  GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1252
1253
0
  g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1254
0
  g_return_if_fail (m->priv->is_client && !m->priv->is_server);
1255
1256
0
  m->priv->is_client = FALSE;
1257
0
}
1258
1259
/* ---------------------------------------------------------------------------------------------------- */