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