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