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