1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
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.
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.
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/>.
18 * Author: David Zeuthen <davidz@redhat.com>
26 #include <sys/types.h>
28 #include <glib/gstdio.h>
37 #include "gdbusauthmechanismsha1.h"
38 #include "gcredentials.h"
39 #include "gdbuserror.h"
40 #include "gioenumtypes.h"
42 #include "gdbusprivate.h"
46 struct _GDBusAuthMechanismSha1Private
50 GDBusAuthMechanismState state;
52 /* used on the client side */
55 /* used on the server side */
57 gchar *server_challenge;
60 static gint mechanism_get_priority (void);
61 static const gchar *mechanism_get_name (void);
63 static gboolean mechanism_is_supported (GDBusAuthMechanism *mechanism);
64 static gchar *mechanism_encode_data (GDBusAuthMechanism *mechanism,
68 static gchar *mechanism_decode_data (GDBusAuthMechanism *mechanism,
72 static GDBusAuthMechanismState mechanism_server_get_state (GDBusAuthMechanism *mechanism);
73 static void mechanism_server_initiate (GDBusAuthMechanism *mechanism,
74 const gchar *initial_response,
75 gsize initial_response_len);
76 static void mechanism_server_data_receive (GDBusAuthMechanism *mechanism,
79 static gchar *mechanism_server_data_send (GDBusAuthMechanism *mechanism,
81 static gchar *mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism);
82 static void mechanism_server_shutdown (GDBusAuthMechanism *mechanism);
83 static GDBusAuthMechanismState mechanism_client_get_state (GDBusAuthMechanism *mechanism);
84 static gchar *mechanism_client_initiate (GDBusAuthMechanism *mechanism,
85 gsize *out_initial_response_len);
86 static void mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
89 static gchar *mechanism_client_data_send (GDBusAuthMechanism *mechanism,
91 static void mechanism_client_shutdown (GDBusAuthMechanism *mechanism);
93 /* ---------------------------------------------------------------------------------------------------- */
95 G_DEFINE_TYPE_WITH_PRIVATE (GDBusAuthMechanismSha1, _g_dbus_auth_mechanism_sha1, G_TYPE_DBUS_AUTH_MECHANISM)
97 /* ---------------------------------------------------------------------------------------------------- */
100 _g_dbus_auth_mechanism_sha1_finalize (GObject *object)
102 GDBusAuthMechanismSha1 *mechanism = G_DBUS_AUTH_MECHANISM_SHA1 (object);
104 g_free (mechanism->priv->to_send);
106 g_free (mechanism->priv->cookie);
107 g_free (mechanism->priv->server_challenge);
109 if (G_OBJECT_CLASS (_g_dbus_auth_mechanism_sha1_parent_class)->finalize != NULL)
110 G_OBJECT_CLASS (_g_dbus_auth_mechanism_sha1_parent_class)->finalize (object);
114 _g_dbus_auth_mechanism_sha1_class_init (GDBusAuthMechanismSha1Class *klass)
116 GObjectClass *gobject_class;
117 GDBusAuthMechanismClass *mechanism_class;
119 gobject_class = G_OBJECT_CLASS (klass);
120 gobject_class->finalize = _g_dbus_auth_mechanism_sha1_finalize;
122 mechanism_class = G_DBUS_AUTH_MECHANISM_CLASS (klass);
123 mechanism_class->get_priority = mechanism_get_priority;
124 mechanism_class->get_name = mechanism_get_name;
125 mechanism_class->is_supported = mechanism_is_supported;
126 mechanism_class->encode_data = mechanism_encode_data;
127 mechanism_class->decode_data = mechanism_decode_data;
128 mechanism_class->server_get_state = mechanism_server_get_state;
129 mechanism_class->server_initiate = mechanism_server_initiate;
130 mechanism_class->server_data_receive = mechanism_server_data_receive;
131 mechanism_class->server_data_send = mechanism_server_data_send;
132 mechanism_class->server_get_reject_reason = mechanism_server_get_reject_reason;
133 mechanism_class->server_shutdown = mechanism_server_shutdown;
134 mechanism_class->client_get_state = mechanism_client_get_state;
135 mechanism_class->client_initiate = mechanism_client_initiate;
136 mechanism_class->client_data_receive = mechanism_client_data_receive;
137 mechanism_class->client_data_send = mechanism_client_data_send;
138 mechanism_class->client_shutdown = mechanism_client_shutdown;
142 _g_dbus_auth_mechanism_sha1_init (GDBusAuthMechanismSha1 *mechanism)
144 mechanism->priv = _g_dbus_auth_mechanism_sha1_get_instance_private (mechanism);
147 /* ---------------------------------------------------------------------------------------------------- */
150 mechanism_get_priority (void)
156 mechanism_get_name (void)
158 return "DBUS_COOKIE_SHA1";
162 mechanism_is_supported (GDBusAuthMechanism *mechanism)
164 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), FALSE);
169 mechanism_encode_data (GDBusAuthMechanism *mechanism,
179 mechanism_decode_data (GDBusAuthMechanism *mechanism,
187 /* ---------------------------------------------------------------------------------------------------- */
193 ret = g_random_int_range (0, 60);
204 random_ascii_string (guint len)
209 challenge = g_string_new (NULL);
210 for (n = 0; n < len; n++)
211 g_string_append_c (challenge, random_ascii ());
212 return g_string_free (challenge, FALSE);
216 random_blob (guint len)
221 challenge = g_string_new (NULL);
222 for (n = 0; n < len; n++)
223 g_string_append_c (challenge, g_random_int_range (0, 256));
224 return g_string_free (challenge, FALSE);
227 /* ---------------------------------------------------------------------------------------------------- */
229 /* ensure keyring dir exists and permissions are correct */
231 ensure_keyring_directory (GError **error)
236 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
238 e = g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR");
245 path = g_build_filename (g_get_home_dir (),
250 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
252 if (g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION") == NULL)
256 if (stat (path, &statbuf) != 0)
261 g_io_error_from_errno (errsv),
262 _("Error when getting information for directory “%s”: %s"),
269 if ((statbuf.st_mode & 0777) != 0700)
274 _("Permissions on directory “%s” are malformed. Expected mode 0700, got 0%o"),
276 (guint) (statbuf.st_mode & 0777));
283 #warning Please implement permission checking on this non-UNIX platform
290 if (g_mkdir (path, 0700) != 0)
295 g_io_error_from_errno (errsv),
296 _("Error creating directory “%s”: %s"),
308 /* ---------------------------------------------------------------------------------------------------- */
311 append_nibble (GString *s, gint val)
313 g_string_append_c (s, val >= 10 ? ('a' + val - 10) : ('0' + val));
317 hexencode (const gchar *str,
326 s = g_string_new (NULL);
327 for (n = 0; n < len; n++)
333 val = ((const guchar *) str)[n];
334 upper_nibble = val >> 4;
335 lower_nibble = val & 0x0f;
337 append_nibble (s, upper_nibble);
338 append_nibble (s, lower_nibble);
341 return g_string_free (s, FALSE);
344 /* ---------------------------------------------------------------------------------------------------- */
346 /* looks up an entry in the keyring */
348 keyring_lookup_entry (const gchar *cookie_context,
359 g_return_val_if_fail (cookie_context != NULL, NULL);
360 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
367 keyring_dir = ensure_keyring_directory (error);
368 if (keyring_dir == NULL)
371 path = g_build_filename (keyring_dir, cookie_context, NULL);
373 if (!g_file_get_contents (path,
378 g_prefix_error (error,
379 _("Error opening keyring “%s” for reading: "),
383 g_assert (contents != NULL);
385 lines = g_strsplit (contents, "\n", 0);
386 for (n = 0; lines[n] != NULL; n++)
388 const gchar *line = lines[n];
396 tokens = g_strsplit (line, " ", 0);
397 if (g_strv_length (tokens) != 3)
402 _("Line %d of the keyring at “%s” with content “%s” is malformed"),
410 line_id = g_ascii_strtoll (tokens[0], &endp, 10);
416 _("First token of line %d of the keyring at “%s” with content “%s” is malformed"),
424 (void)g_ascii_strtoll (tokens[1], &endp, 10); /* do not care what the timestamp is */
430 _("Second token of line %d of the keyring at “%s” with content “%s” is malformed"),
438 if (line_id == cookie_id)
441 ret = tokens[2]; /* steal pointer */
450 /* BOOH, didn't find the cookie */
454 _("Didn’t find cookie with id %d in the keyring at “%s”"),
459 g_free (keyring_dir);
466 /* function for logging important events that the system administrator should take notice of */
469 _log (const gchar *message,
475 va_start (var_args, message);
476 s = g_strdup_vprintf (message, var_args);
479 /* TODO: might want to send this to syslog instead */
480 g_printerr ("GDBus-DBUS_COOKIE_SHA1: %s\n", s);
485 keyring_acquire_lock (const gchar *path,
492 guint num_create_tries;
496 g_return_val_if_fail (path != NULL, FALSE);
497 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
500 lock = g_strdup_printf ("%s.lock", path);
502 /* This is what the D-Bus spec says
504 * Create a lockfile name by appending ".lock" to the name of the
505 * cookie file. The server should attempt to create this file using
506 * O_CREAT | O_EXCL. If file creation fails, the lock
507 * fails. Servers should retry for a reasonable period of time,
508 * then they may choose to delete an existing lock to keep users
509 * from having to manually delete a stale lock. [1]
511 * [1] : Lockfiles are used instead of real file locking fcntl() because
512 * real locking implementations are still flaky on network filesystems
516 num_create_tries = 0;
520 while (g_file_test (lock, G_FILE_TEST_EXISTS))
522 /* sleep 10ms, then try again */
527 /* ok, we slept 50*10ms = 0.5 seconds. Conclude that the lock file must be
528 * stale (nuke the it from orbit)
530 if (g_unlink (lock) != 0)
535 g_io_error_from_errno (errsv),
536 _("Error deleting stale lock file “%s”: %s"),
541 _log ("Deleted stale lock file '%s'", lock);
546 ret = g_open (lock, O_CREAT |
557 /* EEXIST: pathname already exists and O_CREAT and O_EXCL were used. */
558 if (errsv == EEXISTS)
561 if (num_create_tries < 5)
567 g_io_error_from_errno (errsv),
568 _("Error creating lock file “%s”: %s"),
580 keyring_release_lock (const gchar *path,
587 g_return_val_if_fail (path != NULL, FALSE);
588 g_return_val_if_fail (lock_fd != -1, FALSE);
589 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
592 lock = g_strdup_printf ("%s.lock", path);
593 if (close (lock_fd) != 0)
598 g_io_error_from_errno (errsv),
599 _("Error closing (unlinked) lock file “%s”: %s"),
604 if (g_unlink (lock) != 0)
609 g_io_error_from_errno (errsv),
610 _("Error unlinking lock file “%s”: %s"),
624 /* adds an entry to the keyring, taking care of locking and deleting stale/future entries */
626 keyring_generate_entry (const gchar *cookie_context,
638 GString *new_contents;
643 gboolean changed_file;
646 g_return_val_if_fail (cookie_context != NULL, FALSE);
647 g_return_val_if_fail (out_id != NULL, FALSE);
648 g_return_val_if_fail (out_cookie != NULL, FALSE);
649 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
661 keyring_dir = ensure_keyring_directory (error);
662 if (keyring_dir == NULL)
665 path = g_build_filename (keyring_dir, cookie_context, NULL);
667 lock_fd = keyring_acquire_lock (path, error);
673 if (!g_file_get_contents (path,
678 if (local_error->domain == G_FILE_ERROR && local_error->code == G_FILE_ERROR_NOENT)
680 /* file doesn't have to exist */
681 g_error_free (local_error);
685 g_propagate_prefixed_error (error,
687 _("Error opening keyring “%s” for writing: "),
693 new_contents = g_string_new (NULL);
695 changed_file = FALSE;
698 if (contents != NULL)
701 lines = g_strsplit (contents, "\n", 0);
702 for (n = 0; lines[n] != NULL; n++)
704 const gchar *line = lines[n];
714 tokens = g_strsplit (line, " ", 0);
715 if (g_strv_length (tokens) != 3)
720 _("Line %d of the keyring at “%s” with content “%s” is malformed"),
728 line_id = g_ascii_strtoll (tokens[0], &endp, 10);
734 _("First token of line %d of the keyring at “%s” with content “%s” is malformed"),
742 line_when = g_ascii_strtoll (tokens[1], &endp, 10);
748 _("Second token of line %d of the keyring at “%s” with content “%s” is malformed"),
759 * Once the lockfile has been created, the server loads the
760 * cookie file. It should then delete any cookies that are
761 * old (the timeout can be fairly short), or more than a
762 * reasonable time in the future (so that cookies never
763 * accidentally become permanent, if the clock was set far
764 * into the future at some point). If no recent keys remain,
765 * the server may generate a new key.
771 /* Oddball case: entry is more recent than our current wall-clock time..
772 * This is OK, it means that another server on another machine but with
773 * same $HOME wrote the entry.
775 * So discard the entry if it's more than 1 day in the future ("reasonable
776 * time in the future").
778 if (line_when - now > 24*60*60)
781 _log ("Deleted SHA1 cookie from %" G_GUINT64_FORMAT " seconds in the future", line_when - now);
786 /* Discard entry if it's older than 15 minutes ("can be fairly short") */
787 if (now - line_when > 15*60)
795 changed_file = FALSE;
799 g_string_append_printf (new_contents,
800 "%d %" G_GUINT64_FORMAT " %s\n",
804 max_line_id = MAX (line_id, max_line_id);
805 /* Only reuse entry if not older than 10 minutes.
807 * (We need a bit of grace time compared to 15 minutes above.. otherwise
808 * there's a race where we reuse the 14min59.9 secs old entry and a
809 * split-second later another server purges the now 15 minute old entry.)
811 if (now - line_when < 10 * 60)
816 use_cookie = tokens[2]; /* steal memory */
824 } /* for each line */
831 *out_cookie = use_cookie;
837 *out_id = max_line_id + 1;
838 raw_cookie = random_blob (32);
839 *out_cookie = hexencode (raw_cookie, 32);
842 g_string_append_printf (new_contents,
843 "%d %" G_GUINT64_FORMAT " %s\n",
845 (guint64) time (NULL),
850 /* and now actually write the cookie file if there are changes (this is atomic) */
853 if (!g_file_set_contents (path,
860 g_free (*out_cookie);
872 if (!keyring_release_lock (path, lock_fd, &local_error))
878 *error = local_error;
882 g_prefix_error (error,
883 _("(Additionally, releasing the lock for “%s” also failed: %s) "),
885 local_error->message);
890 g_error_free (local_error);
895 g_free (keyring_dir);
899 if (new_contents != NULL)
900 g_string_free (new_contents, TRUE);
905 /* ---------------------------------------------------------------------------------------------------- */
908 generate_sha1 (const gchar *server_challenge,
909 const gchar *client_challenge,
915 str = g_string_new (server_challenge);
916 g_string_append_c (str, ':');
917 g_string_append (str, client_challenge);
918 g_string_append_c (str, ':');
919 g_string_append (str, cookie);
920 sha1 = g_compute_checksum_for_string (G_CHECKSUM_SHA1, str->str, -1);
921 g_string_free (str, TRUE);
926 /* ---------------------------------------------------------------------------------------------------- */
928 static GDBusAuthMechanismState
929 mechanism_server_get_state (GDBusAuthMechanism *mechanism)
931 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
933 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
934 g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
936 return m->priv->state;
940 mechanism_server_initiate (GDBusAuthMechanism *mechanism,
941 const gchar *initial_response,
942 gsize initial_response_len)
944 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
946 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
947 g_return_if_fail (!m->priv->is_server && !m->priv->is_client);
949 m->priv->is_server = TRUE;
950 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
952 if (initial_response != NULL && strlen (initial_response) > 0)
958 uid = g_ascii_strtoll (initial_response, &endp, 10);
961 if (uid == getuid ())
963 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
966 #elif defined(G_OS_WIN32)
968 sid = _g_dbus_win32_get_user_sid ();
969 if (g_strcmp0 (initial_response, sid) == 0)
970 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
973 #error Please implement for your OS
979 mechanism_server_data_receive (GDBusAuthMechanism *mechanism,
983 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
985 const gchar *client_challenge;
986 const gchar *alleged_sha1;
989 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
990 g_return_if_fail (m->priv->is_server && !m->priv->is_client);
991 g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
996 tokens = g_strsplit (data, " ", 0);
997 if (g_strv_length (tokens) != 2)
999 g_warning ("Malformed data '%s'", data);
1000 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1004 client_challenge = tokens[0];
1005 alleged_sha1 = tokens[1];
1007 sha1 = generate_sha1 (m->priv->server_challenge, client_challenge, m->priv->cookie);
1009 if (g_strcmp0 (sha1, alleged_sha1) == 0)
1011 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
1015 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1019 g_strfreev (tokens);
1024 mechanism_server_data_send (GDBusAuthMechanism *mechanism,
1025 gsize *out_data_len)
1027 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1030 const gchar *cookie_context;
1033 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1034 g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
1035 g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
1039 /* TODO: use GDBusAuthObserver here to get the cookie context to use? */
1040 cookie_context = "org_gtk_gdbus_general";
1044 if (!keyring_generate_entry (cookie_context,
1049 g_warning ("Error adding entry to keyring: %s", error->message);
1050 g_error_free (error);
1051 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1055 m->priv->server_challenge = random_ascii_string (16);
1056 s = g_strdup_printf ("%s %d %s",
1059 m->priv->server_challenge);
1061 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
1068 mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism)
1070 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1072 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1073 g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
1074 g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
1076 /* can never end up here because we are never in the REJECTED state */
1077 g_assert_not_reached ();
1083 mechanism_server_shutdown (GDBusAuthMechanism *mechanism)
1085 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1087 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1088 g_return_if_fail (m->priv->is_server && !m->priv->is_client);
1090 m->priv->is_server = FALSE;
1093 /* ---------------------------------------------------------------------------------------------------- */
1095 static GDBusAuthMechanismState
1096 mechanism_client_get_state (GDBusAuthMechanism *mechanism)
1098 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1100 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
1101 g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
1103 return m->priv->state;
1107 mechanism_client_initiate (GDBusAuthMechanism *mechanism,
1108 gsize *out_initial_response_len)
1110 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1111 gchar *initial_response;
1113 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1114 g_return_val_if_fail (!m->priv->is_server && !m->priv->is_client, NULL);
1116 m->priv->is_client = TRUE;
1117 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
1119 *out_initial_response_len = -1;
1122 initial_response = g_strdup_printf ("%" G_GINT64_FORMAT, (gint64) getuid ());
1123 #elif defined (G_OS_WIN32)
1124 initial_response = _g_dbus_win32_get_user_sid ();
1126 #error Please implement for your OS
1128 g_assert (initial_response != NULL);
1130 return initial_response;
1134 mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
1138 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1140 const gchar *cookie_context;
1142 const gchar *server_challenge;
1143 gchar *client_challenge;
1149 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1150 g_return_if_fail (m->priv->is_client && !m->priv->is_server);
1151 g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
1155 client_challenge = NULL;
1157 tokens = g_strsplit (data, " ", 0);
1158 if (g_strv_length (tokens) != 3)
1160 g_warning ("Malformed data '%s'", data);
1161 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1165 cookie_context = tokens[0];
1166 cookie_id = g_ascii_strtoll (tokens[1], &endp, 10);
1169 g_warning ("Malformed cookie_id '%s'", tokens[1]);
1170 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1173 server_challenge = tokens[2];
1176 cookie = keyring_lookup_entry (cookie_context, cookie_id, &error);
1179 g_warning ("Problems looking up entry in keyring: %s", error->message);
1180 g_error_free (error);
1181 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1185 client_challenge = random_ascii_string (16);
1186 sha1 = generate_sha1 (server_challenge, client_challenge, cookie);
1187 m->priv->to_send = g_strdup_printf ("%s %s", client_challenge, sha1);
1189 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
1192 g_strfreev (tokens);
1194 g_free (client_challenge);
1198 mechanism_client_data_send (GDBusAuthMechanism *mechanism,
1199 gsize *out_data_len)
1201 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1203 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1204 g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, NULL);
1205 g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
1207 g_assert (m->priv->to_send != NULL);
1209 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
1211 return g_strdup (m->priv->to_send);
1215 mechanism_client_shutdown (GDBusAuthMechanism *mechanism)
1217 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1219 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1220 g_return_if_fail (m->priv->is_client && !m->priv->is_server);
1222 m->priv->is_client = FALSE;
1225 /* ---------------------------------------------------------------------------------------------------- */