• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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 #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 #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 
G_DEFINE_TYPE_WITH_PRIVATE(GDBusAuthMechanismSha1,_g_dbus_auth_mechanism_sha1,G_TYPE_DBUS_AUTH_MECHANISM)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 {
135   GDBusAuthMechanismSha1 *mechanism = G_DBUS_AUTH_MECHANISM_SHA1 (object);
136 
137   g_free (mechanism->priv->reject_reason);
138   g_free (mechanism->priv->to_send);
139 
140   g_free (mechanism->priv->cookie);
141   g_free (mechanism->priv->server_challenge);
142 
143   if (G_OBJECT_CLASS (_g_dbus_auth_mechanism_sha1_parent_class)->finalize != NULL)
144     G_OBJECT_CLASS (_g_dbus_auth_mechanism_sha1_parent_class)->finalize (object);
145 }
146 
147 static void
_g_dbus_auth_mechanism_sha1_class_init(GDBusAuthMechanismSha1Class * klass)148 _g_dbus_auth_mechanism_sha1_class_init (GDBusAuthMechanismSha1Class *klass)
149 {
150   GObjectClass *gobject_class;
151   GDBusAuthMechanismClass *mechanism_class;
152 
153   gobject_class = G_OBJECT_CLASS (klass);
154   gobject_class->finalize = _g_dbus_auth_mechanism_sha1_finalize;
155 
156   mechanism_class = G_DBUS_AUTH_MECHANISM_CLASS (klass);
157   mechanism_class->get_priority              = mechanism_get_priority;
158   mechanism_class->get_name                  = mechanism_get_name;
159   mechanism_class->is_supported              = mechanism_is_supported;
160   mechanism_class->encode_data               = mechanism_encode_data;
161   mechanism_class->decode_data               = mechanism_decode_data;
162   mechanism_class->server_get_state          = mechanism_server_get_state;
163   mechanism_class->server_initiate           = mechanism_server_initiate;
164   mechanism_class->server_data_receive       = mechanism_server_data_receive;
165   mechanism_class->server_data_send          = mechanism_server_data_send;
166   mechanism_class->server_get_reject_reason  = mechanism_server_get_reject_reason;
167   mechanism_class->server_shutdown           = mechanism_server_shutdown;
168   mechanism_class->client_get_state          = mechanism_client_get_state;
169   mechanism_class->client_initiate           = mechanism_client_initiate;
170   mechanism_class->client_data_receive       = mechanism_client_data_receive;
171   mechanism_class->client_data_send          = mechanism_client_data_send;
172   mechanism_class->client_shutdown           = mechanism_client_shutdown;
173 }
174 
175 static void
_g_dbus_auth_mechanism_sha1_init(GDBusAuthMechanismSha1 * mechanism)176 _g_dbus_auth_mechanism_sha1_init (GDBusAuthMechanismSha1 *mechanism)
177 {
178   mechanism->priv = _g_dbus_auth_mechanism_sha1_get_instance_private (mechanism);
179 }
180 
181 /* ---------------------------------------------------------------------------------------------------- */
182 
183 static gint
mechanism_get_priority(void)184 mechanism_get_priority (void)
185 {
186   return 0;
187 }
188 
189 static const gchar *
mechanism_get_name(void)190 mechanism_get_name (void)
191 {
192   return "DBUS_COOKIE_SHA1";
193 }
194 
195 static gboolean
mechanism_is_supported(GDBusAuthMechanism * mechanism)196 mechanism_is_supported (GDBusAuthMechanism *mechanism)
197 {
198   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), FALSE);
199   return TRUE;
200 }
201 
202 static gchar *
mechanism_encode_data(GDBusAuthMechanism * mechanism,const gchar * data,gsize data_len,gsize * out_data_len)203 mechanism_encode_data (GDBusAuthMechanism   *mechanism,
204                        const gchar          *data,
205                        gsize                 data_len,
206                        gsize                *out_data_len)
207 {
208   return NULL;
209 }
210 
211 
212 static gchar *
mechanism_decode_data(GDBusAuthMechanism * mechanism,const gchar * data,gsize data_len,gsize * out_data_len)213 mechanism_decode_data (GDBusAuthMechanism   *mechanism,
214                        const gchar          *data,
215                        gsize                 data_len,
216                        gsize                *out_data_len)
217 {
218   return NULL;
219 }
220 
221 /* ---------------------------------------------------------------------------------------------------- */
222 
223 static gint
random_ascii(void)224 random_ascii (void)
225 {
226   gint ret;
227   ret = g_random_int_range (0, 60);
228   if (ret < 25)
229     ret += 'A';
230   else if (ret < 50)
231     ret += 'a' - 25;
232   else
233     ret += '0' - 50;
234   return ret;
235 }
236 
237 static gchar *
random_ascii_string(guint len)238 random_ascii_string (guint len)
239 {
240   GString *challenge;
241   guint n;
242 
243   challenge = g_string_new (NULL);
244   for (n = 0; n < len; n++)
245     g_string_append_c (challenge, random_ascii ());
246   return g_string_free (challenge, FALSE);
247 }
248 
249 static gchar *
random_blob(guint len)250 random_blob (guint len)
251 {
252   GString *challenge;
253   guint n;
254 
255   challenge = g_string_new (NULL);
256   for (n = 0; n < len; n++)
257     g_string_append_c (challenge, g_random_int_range (0, 256));
258   return g_string_free (challenge, FALSE);
259 }
260 
261 /* ---------------------------------------------------------------------------------------------------- */
262 
263 /* ensure keyring dir exists and permissions are correct */
264 static gchar *
ensure_keyring_directory(GError ** error)265 ensure_keyring_directory (GError **error)
266 {
267   gchar *path;
268   const gchar *e;
269   gboolean is_setuid;
270 #ifdef G_OS_UNIX
271   struct stat statbuf;
272 #endif
273 
274   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
275 
276   e = g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR");
277   if (e != NULL)
278     {
279       path = g_strdup (e);
280     }
281   else
282     {
283       path = g_build_filename (g_get_home_dir (),
284                                ".dbus-keyrings",
285                                NULL);
286     }
287 
288 #ifdef G_OS_UNIX
289   if (stat (path, &statbuf) != 0)
290     {
291       int errsv = errno;
292 
293       if (errsv != ENOENT)
294         {
295           g_set_error (error,
296                        G_IO_ERROR,
297                        g_io_error_from_errno (errsv),
298                        _("Error when getting information for directory “%s”: %s"),
299                        path,
300                        g_strerror (errsv));
301           g_clear_pointer (&path, g_free);
302           return NULL;
303         }
304     }
305   else if (S_ISDIR (statbuf.st_mode))
306     {
307       if (g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION") == NULL &&
308           (statbuf.st_mode & 0777) != 0700)
309         {
310           g_set_error (error,
311                        G_IO_ERROR,
312                        G_IO_ERROR_FAILED,
313                        _("Permissions on directory “%s” are malformed. Expected mode 0700, got 0%o"),
314                        path,
315                        (guint) (statbuf.st_mode & 0777));
316           g_clear_pointer (&path, g_free);
317           return NULL;
318         }
319 
320       return g_steal_pointer (&path);
321     }
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   is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) ();
339   if (!is_setuid &&
340       g_mkdir_with_parents (path, 0700) != 0)
341     {
342       int errsv = errno;
343       g_set_error (error,
344                    G_IO_ERROR,
345                    g_io_error_from_errno (errsv),
346                    _("Error creating directory “%s”: %s"),
347                    path,
348                    g_strerror (errsv));
349       g_clear_pointer (&path, g_free);
350       return NULL;
351     }
352   else if (is_setuid)
353     {
354       g_set_error (error,
355                    G_IO_ERROR,
356                    G_IO_ERROR_PERMISSION_DENIED,
357                    _("Error creating directory “%s”: %s"),
358                    path,
359                    _("Operation not supported"));
360       g_clear_pointer (&path, g_free);
361       return NULL;
362     }
363 
364   return g_steal_pointer (&path);
365 }
366 
367 /* ---------------------------------------------------------------------------------------------------- */
368 
369 /* looks up an entry in the keyring */
370 static gchar *
keyring_lookup_entry(const gchar * cookie_context,gint cookie_id,GError ** error)371 keyring_lookup_entry (const gchar  *cookie_context,
372                       gint          cookie_id,
373                       GError      **error)
374 {
375   gchar *ret;
376   gchar *keyring_dir;
377   gchar *contents;
378   gchar *path;
379   guint n;
380   gchar **lines;
381 
382   g_return_val_if_fail (cookie_context != NULL, NULL);
383   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
384 
385   ret = NULL;
386   path = NULL;
387   contents = NULL;
388   lines = NULL;
389 
390   keyring_dir = ensure_keyring_directory (error);
391   if (keyring_dir == NULL)
392     goto out;
393 
394   path = g_build_filename (keyring_dir, cookie_context, NULL);
395 
396   if (!g_file_get_contents (path,
397                             &contents,
398                             NULL,
399                             error))
400     {
401       g_prefix_error (error,
402                       _("Error opening keyring “%s” for reading: "),
403                       path);
404       goto out;
405     }
406   g_assert (contents != NULL);
407 
408   lines = g_strsplit (contents, "\n", 0);
409   for (n = 0; lines[n] != NULL; n++)
410     {
411       const gchar *line = lines[n];
412       gchar **tokens;
413       gchar *endp;
414       gint line_id;
415 
416       if (line[0] == '\0')
417         continue;
418 
419       tokens = g_strsplit (line, " ", 0);
420       if (g_strv_length (tokens) != 3)
421         {
422           g_set_error (error,
423                        G_IO_ERROR,
424                        G_IO_ERROR_FAILED,
425                        _("Line %d of the keyring at “%s” with content “%s” is malformed"),
426                        n + 1,
427                        path,
428                        line);
429           g_strfreev (tokens);
430           goto out;
431         }
432 
433       line_id = g_ascii_strtoll (tokens[0], &endp, 10);
434       if (*endp != '\0')
435         {
436           g_set_error (error,
437                        G_IO_ERROR,
438                        G_IO_ERROR_FAILED,
439                        _("First token of line %d of the keyring at “%s” with content “%s” is malformed"),
440                        n + 1,
441                        path,
442                        line);
443           g_strfreev (tokens);
444           goto out;
445         }
446 
447       (void)g_ascii_strtoll (tokens[1], &endp, 10); /* do not care what the timestamp is */
448       if (*endp != '\0')
449         {
450           g_set_error (error,
451                        G_IO_ERROR,
452                        G_IO_ERROR_FAILED,
453                        _("Second token of line %d of the keyring at “%s” with content “%s” is malformed"),
454                        n + 1,
455                        path,
456                        line);
457           g_strfreev (tokens);
458           goto out;
459         }
460 
461       if (line_id == cookie_id)
462         {
463           /* YAY, success */
464           ret = tokens[2]; /* steal pointer */
465           tokens[2] = NULL;
466           g_strfreev (tokens);
467           goto out;
468         }
469 
470       g_strfreev (tokens);
471     }
472 
473   /* BOOH, didn't find the cookie */
474   g_set_error (error,
475                G_IO_ERROR,
476                G_IO_ERROR_FAILED,
477                _("Didn’t find cookie with id %d in the keyring at “%s”"),
478                cookie_id,
479                path);
480 
481  out:
482   g_free (keyring_dir);
483   g_free (path);
484   g_free (contents);
485   g_strfreev (lines);
486   return ret;
487 }
488 
489 /* function for logging important events that the system administrator should take notice of */
490 G_GNUC_PRINTF(1, 2)
491 static void
_log(const gchar * message,...)492 _log (const gchar *message,
493       ...)
494 {
495   gchar *s;
496   va_list var_args;
497 
498   va_start (var_args, message);
499   s = g_strdup_vprintf (message, var_args);
500   va_end (var_args);
501 
502   /* TODO: might want to send this to syslog instead */
503   g_printerr ("GDBus-DBUS_COOKIE_SHA1: %s\n", s);
504   g_free (s);
505 }
506 
507 /* Returns FD for lock file, if it was created exclusively (didn't exist already,
508  * and was created successfully) */
509 static gint
create_lock_exclusive(const gchar * lock_path,GError ** error)510 create_lock_exclusive (const gchar  *lock_path,
511                        GError      **error)
512 {
513   int errsv;
514   gint ret;
515 
516   ret = g_open (lock_path, O_CREAT | O_EXCL, 0600);
517   errsv = errno;
518   if (ret < 0)
519     {
520       g_set_error (error,
521                    G_IO_ERROR,
522                    g_io_error_from_errno (errsv),
523                    _("Error creating lock file “%s”: %s"),
524                    lock_path,
525                    g_strerror (errsv));
526       return -1;
527     }
528 
529   return ret;
530 }
531 
532 static gint
keyring_acquire_lock(const gchar * path,GError ** error)533 keyring_acquire_lock (const gchar  *path,
534                       GError      **error)
535 {
536   gchar *lock = NULL;
537   gint ret;
538   guint num_tries;
539   int errsv;
540 
541   /* Total possible sleep period = max_tries * timeout_usec = 0.5s */
542   const guint max_tries = 50;
543   const guint timeout_usec = 1000 * 10;
544 
545   g_return_val_if_fail (path != NULL, -1);
546   g_return_val_if_fail (error == NULL || *error == NULL, -1);
547 
548   ret = -1;
549   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   for (num_tries = 0; num_tries < max_tries; num_tries++)
566     {
567       /* Ignore the error until the final call. */
568       ret = create_lock_exclusive (lock, NULL);
569       if (ret >= 0)
570         break;
571 
572       /* sleep 10ms, then try again */
573       g_usleep (timeout_usec);
574     }
575 
576   if (num_tries == max_tries)
577     {
578       /* ok, we slept 50*10ms = 0.5 seconds. Conclude that the lock file must be
579        * stale (nuke it from orbit)
580        */
581       if (g_unlink (lock) != 0)
582         {
583           errsv = errno;
584           g_set_error (error,
585                        G_IO_ERROR,
586                        g_io_error_from_errno (errsv),
587                        _("Error deleting stale lock file “%s”: %s"),
588                        lock,
589                        g_strerror (errsv));
590           goto out;
591         }
592 
593       _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       ret = create_lock_exclusive (lock, error);
597       if (ret < 0)
598         goto out;
599     }
600 
601 out:
602   g_free (lock);
603   return ret;
604 }
605 
606 static gboolean
keyring_release_lock(const gchar * path,gint lock_fd,GError ** error)607 keyring_release_lock (const gchar  *path,
608                       gint          lock_fd,
609                       GError      **error)
610 {
611   gchar *lock;
612   gboolean ret;
613 
614   g_return_val_if_fail (path != NULL, FALSE);
615   g_return_val_if_fail (lock_fd != -1, FALSE);
616   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
617 
618   ret = FALSE;
619   lock = g_strdup_printf ("%s.lock", path);
620   if (close (lock_fd) != 0)
621     {
622       int errsv = errno;
623       g_set_error (error,
624                    G_IO_ERROR,
625                    g_io_error_from_errno (errsv),
626                    _("Error closing (unlinked) lock file “%s”: %s"),
627                    lock,
628                    g_strerror (errsv));
629       goto out;
630     }
631   if (g_unlink (lock) != 0)
632     {
633       int errsv = errno;
634       g_set_error (error,
635                    G_IO_ERROR,
636                    g_io_error_from_errno (errsv),
637                    _("Error unlinking lock file “%s”: %s"),
638                    lock,
639                    g_strerror (errsv));
640       goto out;
641     }
642 
643   ret = TRUE;
644 
645  out:
646   g_free (lock);
647   return ret;
648 }
649 
650 
651 /* adds an entry to the keyring, taking care of locking and deleting stale/future entries */
652 static gboolean
keyring_generate_entry(const gchar * cookie_context,gint * out_id,gchar ** out_cookie,GError ** error)653 keyring_generate_entry (const gchar  *cookie_context,
654                         gint         *out_id,
655                         gchar       **out_cookie,
656                         GError      **error)
657 {
658   gboolean ret;
659   gchar *keyring_dir;
660   gchar *path;
661   gchar *contents;
662   GError *local_error;
663   gchar **lines;
664   gint max_line_id;
665   GString *new_contents;
666   gint64 now;
667   gboolean have_id;
668   gint use_id;
669   gchar *use_cookie;
670   gboolean changed_file;
671   gint lock_fd;
672 
673   g_return_val_if_fail (cookie_context != NULL, FALSE);
674   g_return_val_if_fail (out_id != NULL, FALSE);
675   g_return_val_if_fail (out_cookie != NULL, FALSE);
676   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
677 
678   ret = FALSE;
679   path = NULL;
680   contents = NULL;
681   lines = NULL;
682   new_contents = NULL;
683   have_id = FALSE;
684   use_id = 0;
685   use_cookie = NULL;
686   lock_fd = -1;
687 
688   keyring_dir = ensure_keyring_directory (error);
689   if (keyring_dir == NULL)
690     goto out;
691 
692   path = g_build_filename (keyring_dir, cookie_context, NULL);
693 
694   lock_fd = keyring_acquire_lock (path, error);
695   if (lock_fd == -1)
696     goto out;
697 
698   local_error = NULL;
699   contents = NULL;
700   if (!g_file_get_contents (path,
701                             &contents,
702                             NULL,
703                             &local_error))
704     {
705       if (local_error->domain == G_FILE_ERROR && local_error->code == G_FILE_ERROR_NOENT)
706         {
707           /* file doesn't have to exist */
708           g_error_free (local_error);
709         }
710       else
711         {
712           g_propagate_prefixed_error (error,
713                                       local_error,
714                                       _("Error opening keyring “%s” for writing: "),
715                                       path);
716           goto out;
717         }
718     }
719 
720   new_contents = g_string_new (NULL);
721   now = g_get_real_time () / G_USEC_PER_SEC;
722   changed_file = FALSE;
723 
724   max_line_id = 0;
725   if (contents != NULL)
726     {
727       guint n;
728       lines = g_strsplit (contents, "\n", 0);
729       for (n = 0; lines[n] != NULL; n++)
730         {
731           const gchar *line = lines[n];
732           gchar **tokens;
733           gchar *endp;
734           gint line_id;
735           gint64 line_when;
736           gboolean keep_entry;
737 
738           if (line[0] == '\0')
739             continue;
740 
741           tokens = g_strsplit (line, " ", 0);
742           if (g_strv_length (tokens) != 3)
743             {
744               g_set_error (error,
745                            G_IO_ERROR,
746                            G_IO_ERROR_FAILED,
747                            _("Line %d of the keyring at “%s” with content “%s” is malformed"),
748                            n + 1,
749                            path,
750                            line);
751               g_strfreev (tokens);
752               goto out;
753             }
754 
755           line_id = g_ascii_strtoll (tokens[0], &endp, 10);
756           if (*endp != '\0')
757             {
758               g_set_error (error,
759                            G_IO_ERROR,
760                            G_IO_ERROR_FAILED,
761                            _("First token of line %d of the keyring at “%s” with content “%s” is malformed"),
762                            n + 1,
763                            path,
764                            line);
765               g_strfreev (tokens);
766               goto out;
767             }
768 
769           line_when = g_ascii_strtoll (tokens[1], &endp, 10);
770           if (*endp != '\0')
771             {
772               g_set_error (error,
773                            G_IO_ERROR,
774                            G_IO_ERROR_FAILED,
775                            _("Second token of 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 
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           keep_entry = TRUE;
796           if (line_when > now)
797             {
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               if (line_when - now > MAX_TIME_TRAVEL_SECONDS)
802                 {
803                   keep_entry = FALSE;
804                   _log ("Deleted SHA1 cookie from %" G_GUINT64_FORMAT " seconds in the future", line_when - now);
805                 }
806             }
807           else
808             {
809               /* Discard entry if it's too old. */
810               if (now - line_when > EXPIRE_KEYS_TIMEOUT_SECONDS)
811                 {
812                   keep_entry = FALSE;
813                 }
814             }
815 
816           if (!keep_entry)
817             {
818               changed_file = FALSE;
819             }
820           else
821             {
822               g_string_append_printf (new_contents,
823                                       "%d %" G_GUINT64_FORMAT " %s\n",
824                                       line_id,
825                                       line_when,
826                                       tokens[2]);
827               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               if (now - line_when < NEW_KEY_TIMEOUT_SECONDS)
835                 {
836                   if (!have_id)
837                     {
838                       use_id = line_id;
839                       use_cookie = tokens[2]; /* steal memory */
840                       tokens[2] = NULL;
841                       have_id = TRUE;
842                     }
843                 }
844             }
845           g_strfreev (tokens);
846         }
847     } /* for each line */
848 
849   ret = TRUE;
850 
851   if (have_id)
852     {
853       *out_id = use_id;
854       *out_cookie = use_cookie;
855       use_cookie = NULL;
856     }
857   else
858     {
859       gchar *raw_cookie;
860       *out_id = max_line_id + 1;
861       raw_cookie = random_blob (32);
862       *out_cookie = _g_dbus_hexencode (raw_cookie, 32);
863       g_free (raw_cookie);
864 
865       g_string_append_printf (new_contents,
866                               "%d %" G_GINT64_FORMAT " %s\n",
867                               *out_id,
868                               g_get_real_time () / G_USEC_PER_SEC,
869                               *out_cookie);
870       changed_file = TRUE;
871     }
872 
873   /* and now actually write the cookie file if there are changes (this is atomic) */
874   if (changed_file)
875     {
876       if (!g_file_set_contents_full (path,
877                                      new_contents->str,
878                                      -1,
879                                      G_FILE_SET_CONTENTS_CONSISTENT,
880                                      0600,
881                                      error))
882         {
883           *out_id = 0;
884           *out_cookie = 0;
885           g_free (*out_cookie);
886           ret = FALSE;
887           goto out;
888         }
889     }
890 
891  out:
892 
893   if (lock_fd != -1)
894     {
895       GError *local_error;
896       local_error = NULL;
897       if (!keyring_release_lock (path, lock_fd, &local_error))
898         {
899           if (error != NULL)
900             {
901               if (*error == NULL)
902                 {
903                   *error = local_error;
904                 }
905               else
906                 {
907                   g_prefix_error (error,
908                                   _("(Additionally, releasing the lock for “%s” also failed: %s) "),
909                                   path,
910                                   local_error->message);
911                 }
912             }
913           else
914             {
915               g_error_free (local_error);
916             }
917         }
918     }
919 
920   g_free (keyring_dir);
921   g_free (path);
922   g_strfreev (lines);
923   g_free (contents);
924   if (new_contents != NULL)
925     g_string_free (new_contents, TRUE);
926   g_free (use_cookie);
927   return ret;
928 }
929 
930 /* ---------------------------------------------------------------------------------------------------- */
931 
932 static gchar *
generate_sha1(const gchar * server_challenge,const gchar * client_challenge,const gchar * cookie)933 generate_sha1 (const gchar *server_challenge,
934                const gchar *client_challenge,
935                const gchar *cookie)
936 {
937   GString *str;
938   gchar *sha1;
939 
940   str = g_string_new (server_challenge);
941   g_string_append_c (str, ':');
942   g_string_append (str, client_challenge);
943   g_string_append_c (str, ':');
944   g_string_append (str, cookie);
945   sha1 = g_compute_checksum_for_string (G_CHECKSUM_SHA1, str->str, -1);
946   g_string_free (str, TRUE);
947 
948   return sha1;
949 }
950 
951 /* ---------------------------------------------------------------------------------------------------- */
952 
953 static GDBusAuthMechanismState
mechanism_server_get_state(GDBusAuthMechanism * mechanism)954 mechanism_server_get_state (GDBusAuthMechanism   *mechanism)
955 {
956   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
957 
958   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
959   g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
960 
961   return m->priv->state;
962 }
963 
964 static void
mechanism_server_initiate(GDBusAuthMechanism * mechanism,const gchar * initial_response,gsize initial_response_len)965 mechanism_server_initiate (GDBusAuthMechanism   *mechanism,
966                            const gchar          *initial_response,
967                            gsize                 initial_response_len)
968 {
969   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
970 
971   g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
972   g_return_if_fail (!m->priv->is_server && !m->priv->is_client);
973 
974   m->priv->is_server = TRUE;
975   m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
976 
977   if (initial_response != NULL && initial_response_len > 0)
978     {
979 #ifdef G_OS_UNIX
980       gint64 uid;
981       gchar *endp;
982 
983       uid = g_ascii_strtoll (initial_response, &endp, 10);
984       if (*endp == '\0')
985         {
986           if (uid == getuid ())
987             {
988               m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
989             }
990         }
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     }
1001 }
1002 
1003 static void
mechanism_server_data_receive(GDBusAuthMechanism * mechanism,const gchar * data,gsize data_len)1004 mechanism_server_data_receive (GDBusAuthMechanism   *mechanism,
1005                                const gchar          *data,
1006                                gsize                 data_len)
1007 {
1008   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1009   gchar **tokens;
1010   const gchar *client_challenge;
1011   const gchar *alleged_sha1;
1012   gchar *sha1;
1013 
1014   g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1015   g_return_if_fail (m->priv->is_server && !m->priv->is_client);
1016   g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
1017 
1018   tokens = NULL;
1019   sha1 = NULL;
1020 
1021   tokens = g_strsplit (data, " ", 0);
1022   if (g_strv_length (tokens) != 2)
1023     {
1024       g_free (m->priv->reject_reason);
1025       m->priv->reject_reason = g_strdup_printf ("Malformed data '%s'", data);
1026       m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1027       goto out;
1028     }
1029 
1030   client_challenge = tokens[0];
1031   alleged_sha1 = tokens[1];
1032 
1033   sha1 = generate_sha1 (m->priv->server_challenge, client_challenge, m->priv->cookie);
1034 
1035   if (g_strcmp0 (sha1, alleged_sha1) == 0)
1036     {
1037       m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
1038     }
1039   else
1040     {
1041       g_free (m->priv->reject_reason);
1042       m->priv->reject_reason = g_strdup_printf ("SHA-1 mismatch");
1043       m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1044     }
1045 
1046  out:
1047   g_strfreev (tokens);
1048   g_free (sha1);
1049 }
1050 
1051 static gchar *
mechanism_server_data_send(GDBusAuthMechanism * mechanism,gsize * out_data_len)1052 mechanism_server_data_send (GDBusAuthMechanism   *mechanism,
1053                             gsize                *out_data_len)
1054 {
1055   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1056   gchar *s;
1057   gint cookie_id;
1058   const gchar *cookie_context;
1059   GError *error;
1060 
1061   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1062   g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
1063   g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
1064 
1065   s = NULL;
1066   *out_data_len = 0;
1067 
1068   /* TODO: use GDBusAuthObserver here to get the cookie context to use? */
1069   cookie_context = "org_gtk_gdbus_general";
1070 
1071   cookie_id = -1;
1072   error = NULL;
1073   if (!keyring_generate_entry (cookie_context,
1074                                &cookie_id,
1075                                &m->priv->cookie,
1076                                &error))
1077     {
1078       g_free (m->priv->reject_reason);
1079       m->priv->reject_reason = g_strdup_printf ("Error adding entry to keyring: %s", error->message);
1080       g_error_free (error);
1081       m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1082       goto out;
1083     }
1084 
1085   m->priv->server_challenge = random_ascii_string (16);
1086   s = g_strdup_printf ("%s %d %s",
1087                        cookie_context,
1088                        cookie_id,
1089                        m->priv->server_challenge);
1090   *out_data_len = strlen (s);
1091 
1092   m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
1093 
1094  out:
1095   return s;
1096 }
1097 
1098 static gchar *
mechanism_server_get_reject_reason(GDBusAuthMechanism * mechanism)1099 mechanism_server_get_reject_reason (GDBusAuthMechanism   *mechanism)
1100 {
1101   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1102 
1103   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1104   g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
1105   g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
1106 
1107   return g_strdup (m->priv->reject_reason);
1108 }
1109 
1110 static void
mechanism_server_shutdown(GDBusAuthMechanism * mechanism)1111 mechanism_server_shutdown (GDBusAuthMechanism   *mechanism)
1112 {
1113   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1114 
1115   g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1116   g_return_if_fail (m->priv->is_server && !m->priv->is_client);
1117 
1118   m->priv->is_server = FALSE;
1119 }
1120 
1121 /* ---------------------------------------------------------------------------------------------------- */
1122 
1123 static GDBusAuthMechanismState
mechanism_client_get_state(GDBusAuthMechanism * mechanism)1124 mechanism_client_get_state (GDBusAuthMechanism   *mechanism)
1125 {
1126   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1127 
1128   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
1129   g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
1130 
1131   return m->priv->state;
1132 }
1133 
1134 static gchar *
mechanism_client_initiate(GDBusAuthMechanism * mechanism,gsize * out_initial_response_len)1135 mechanism_client_initiate (GDBusAuthMechanism   *mechanism,
1136                            gsize                *out_initial_response_len)
1137 {
1138   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1139   gchar *initial_response;
1140 
1141   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1142   g_return_val_if_fail (!m->priv->is_server && !m->priv->is_client, NULL);
1143 
1144   m->priv->is_client = TRUE;
1145   m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
1146 
1147   *out_initial_response_len = 0;
1148 
1149 #ifdef G_OS_UNIX
1150   initial_response = g_strdup_printf ("%" G_GINT64_FORMAT, (gint64) getuid ());
1151   *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   g_assert (initial_response != NULL);
1159 
1160   return initial_response;
1161 }
1162 
1163 static void
mechanism_client_data_receive(GDBusAuthMechanism * mechanism,const gchar * data,gsize data_len)1164 mechanism_client_data_receive (GDBusAuthMechanism   *mechanism,
1165                                const gchar          *data,
1166                                gsize                 data_len)
1167 {
1168   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1169   gchar **tokens;
1170   const gchar *cookie_context;
1171   guint cookie_id;
1172   const gchar *server_challenge;
1173   gchar *client_challenge;
1174   gchar *endp;
1175   gchar *cookie;
1176   GError *error;
1177   gchar *sha1;
1178 
1179   g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1180   g_return_if_fail (m->priv->is_client && !m->priv->is_server);
1181   g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
1182 
1183   tokens = NULL;
1184   cookie = NULL;
1185   client_challenge = NULL;
1186 
1187   tokens = g_strsplit (data, " ", 0);
1188   if (g_strv_length (tokens) != 3)
1189     {
1190       g_free (m->priv->reject_reason);
1191       m->priv->reject_reason = g_strdup_printf ("Malformed data '%s'", data);
1192       m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1193       goto out;
1194     }
1195 
1196   cookie_context = tokens[0];
1197   cookie_id = g_ascii_strtoll (tokens[1], &endp, 10);
1198   if (*endp != '\0')
1199     {
1200       g_free (m->priv->reject_reason);
1201       m->priv->reject_reason = g_strdup_printf ("Malformed cookie_id '%s'", tokens[1]);
1202       m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1203       goto out;
1204     }
1205   server_challenge = tokens[2];
1206 
1207   error = NULL;
1208   cookie = keyring_lookup_entry (cookie_context, cookie_id, &error);
1209   if (cookie == NULL)
1210     {
1211       g_free (m->priv->reject_reason);
1212       m->priv->reject_reason = g_strdup_printf ("Problems looking up entry in keyring: %s", error->message);
1213       g_error_free (error);
1214       m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1215       goto out;
1216     }
1217 
1218   client_challenge = random_ascii_string (16);
1219   sha1 = generate_sha1 (server_challenge, client_challenge, cookie);
1220   m->priv->to_send = g_strdup_printf ("%s %s", client_challenge, sha1);
1221   g_free (sha1);
1222   m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
1223 
1224  out:
1225   g_strfreev (tokens);
1226   g_free (cookie);
1227   g_free (client_challenge);
1228 }
1229 
1230 static gchar *
mechanism_client_data_send(GDBusAuthMechanism * mechanism,gsize * out_data_len)1231 mechanism_client_data_send (GDBusAuthMechanism   *mechanism,
1232                             gsize                *out_data_len)
1233 {
1234   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1235 
1236   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1237   g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, NULL);
1238   g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
1239 
1240   g_assert (m->priv->to_send != NULL);
1241 
1242   m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
1243 
1244   *out_data_len = strlen (m->priv->to_send);
1245   return g_strdup (m->priv->to_send);
1246 }
1247 
1248 static void
mechanism_client_shutdown(GDBusAuthMechanism * mechanism)1249 mechanism_client_shutdown (GDBusAuthMechanism   *mechanism)
1250 {
1251   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1252 
1253   g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1254   g_return_if_fail (m->priv->is_client && !m->priv->is_server);
1255 
1256   m->priv->is_client = FALSE;
1257 }
1258 
1259 /* ---------------------------------------------------------------------------------------------------- */
1260