1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2009 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 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, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: David Zeuthen <davidz@redhat.com>
25 #include <glib/gi18n.h>
27 #include "gdbusauthmechanismsha1.h"
28 #include "gcredentials.h"
29 #include "gdbuserror.h"
30 #include "gioenumtypes.h"
35 #include <sys/types.h>
41 #include <glib/gstdio.h>
43 struct _GDBusAuthMechanismSha1Private
47 GDBusAuthMechanismState state;
49 /* used on the client side */
52 /* used on the server side */
54 gchar *server_challenge;
57 static gint mechanism_get_priority (void);
58 static const gchar *mechanism_get_name (void);
60 static gboolean mechanism_is_supported (GDBusAuthMechanism *mechanism);
61 static gchar *mechanism_encode_data (GDBusAuthMechanism *mechanism,
65 static gchar *mechanism_decode_data (GDBusAuthMechanism *mechanism,
69 static GDBusAuthMechanismState mechanism_server_get_state (GDBusAuthMechanism *mechanism);
70 static void mechanism_server_initiate (GDBusAuthMechanism *mechanism,
71 const gchar *initial_response,
72 gsize initial_response_len);
73 static void mechanism_server_data_receive (GDBusAuthMechanism *mechanism,
76 static gchar *mechanism_server_data_send (GDBusAuthMechanism *mechanism,
78 static gchar *mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism);
79 static void mechanism_server_shutdown (GDBusAuthMechanism *mechanism);
80 static GDBusAuthMechanismState mechanism_client_get_state (GDBusAuthMechanism *mechanism);
81 static gchar *mechanism_client_initiate (GDBusAuthMechanism *mechanism,
82 gsize *out_initial_response_len);
83 static void mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
86 static gchar *mechanism_client_data_send (GDBusAuthMechanism *mechanism,
88 static void mechanism_client_shutdown (GDBusAuthMechanism *mechanism);
90 /* ---------------------------------------------------------------------------------------------------- */
92 G_DEFINE_TYPE (GDBusAuthMechanismSha1, _g_dbus_auth_mechanism_sha1, G_TYPE_DBUS_AUTH_MECHANISM);
94 /* ---------------------------------------------------------------------------------------------------- */
97 _g_dbus_auth_mechanism_sha1_finalize (GObject *object)
99 GDBusAuthMechanismSha1 *mechanism = G_DBUS_AUTH_MECHANISM_SHA1 (object);
101 g_free (mechanism->priv->to_send);
103 g_free (mechanism->priv->cookie);
104 g_free (mechanism->priv->server_challenge);
106 if (G_OBJECT_CLASS (_g_dbus_auth_mechanism_sha1_parent_class)->finalize != NULL)
107 G_OBJECT_CLASS (_g_dbus_auth_mechanism_sha1_parent_class)->finalize (object);
111 _g_dbus_auth_mechanism_sha1_class_init (GDBusAuthMechanismSha1Class *klass)
113 GObjectClass *gobject_class;
114 GDBusAuthMechanismClass *mechanism_class;
116 g_type_class_add_private (klass, sizeof (GDBusAuthMechanismSha1Private));
118 gobject_class = G_OBJECT_CLASS (klass);
119 gobject_class->finalize = _g_dbus_auth_mechanism_sha1_finalize;
121 mechanism_class = G_DBUS_AUTH_MECHANISM_CLASS (klass);
122 mechanism_class->get_priority = mechanism_get_priority;
123 mechanism_class->get_name = mechanism_get_name;
124 mechanism_class->is_supported = mechanism_is_supported;
125 mechanism_class->encode_data = mechanism_encode_data;
126 mechanism_class->decode_data = mechanism_decode_data;
127 mechanism_class->server_get_state = mechanism_server_get_state;
128 mechanism_class->server_initiate = mechanism_server_initiate;
129 mechanism_class->server_data_receive = mechanism_server_data_receive;
130 mechanism_class->server_data_send = mechanism_server_data_send;
131 mechanism_class->server_get_reject_reason = mechanism_server_get_reject_reason;
132 mechanism_class->server_shutdown = mechanism_server_shutdown;
133 mechanism_class->client_get_state = mechanism_client_get_state;
134 mechanism_class->client_initiate = mechanism_client_initiate;
135 mechanism_class->client_data_receive = mechanism_client_data_receive;
136 mechanism_class->client_data_send = mechanism_client_data_send;
137 mechanism_class->client_shutdown = mechanism_client_shutdown;
141 _g_dbus_auth_mechanism_sha1_init (GDBusAuthMechanismSha1 *mechanism)
143 mechanism->priv = G_TYPE_INSTANCE_GET_PRIVATE (mechanism,
144 G_TYPE_DBUS_AUTH_MECHANISM_SHA1,
145 GDBusAuthMechanismSha1Private);
148 /* ---------------------------------------------------------------------------------------------------- */
151 mechanism_get_priority (void)
157 mechanism_get_name (void)
159 return "DBUS_COOKIE_SHA1";
163 mechanism_is_supported (GDBusAuthMechanism *mechanism)
165 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), FALSE);
170 mechanism_encode_data (GDBusAuthMechanism *mechanism,
180 mechanism_decode_data (GDBusAuthMechanism *mechanism,
188 /* ---------------------------------------------------------------------------------------------------- */
194 ret = g_random_int_range (0, 60);
205 random_ascii_string (guint len)
210 challenge = g_string_new (NULL);
211 for (n = 0; n < len; n++)
212 g_string_append_c (challenge, random_ascii ());
213 return g_string_free (challenge, FALSE);
217 random_blob (guint len)
222 challenge = g_string_new (NULL);
223 for (n = 0; n < len; n++)
224 g_string_append_c (challenge, g_random_int_range (0, 256));
225 return g_string_free (challenge, FALSE);
228 /* ---------------------------------------------------------------------------------------------------- */
230 /* ensure keyring dir exists and permissions are correct */
232 ensure_keyring_directory (GError **error)
237 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
239 e = g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR");
246 path = g_build_filename (g_get_home_dir (),
251 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
253 if (g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION") == NULL)
257 if (stat (path, &statbuf) != 0)
261 g_io_error_from_errno (errno),
262 _("Error statting directory `%s': %s"),
269 if ((statbuf.st_mode & 0777) != 0700)
274 _("Permissions on directory `%s' are malformed. Expected mode 0700, got 0%o"),
276 statbuf.st_mode & 0777);
282 #error Please implement permission checking on non-UNIX platforms
288 if (g_mkdir (path, 0700) != 0)
292 g_io_error_from_errno (errno),
293 _("Error creating directory `%s': %s"),
305 /* ---------------------------------------------------------------------------------------------------- */
308 append_nibble (GString *s, gint val)
310 g_string_append_c (s, val >= 10 ? ('a' + val - 10) : ('0' + val));
314 hexencode (const gchar *str,
323 s = g_string_new (NULL);
324 for (n = 0; n < len; n++)
330 val = ((const guchar *) str)[n];
331 upper_nibble = val >> 4;
332 lower_nibble = val & 0x0f;
334 append_nibble (s, upper_nibble);
335 append_nibble (s, lower_nibble);
338 return g_string_free (s, FALSE);
341 /* ---------------------------------------------------------------------------------------------------- */
343 /* looks up an entry in the keyring */
345 keyring_lookup_entry (const gchar *cookie_context,
356 g_return_val_if_fail (cookie_context != NULL, FALSE);
357 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
364 keyring_dir = ensure_keyring_directory (error);
365 if (keyring_dir == NULL)
368 path = g_build_filename (keyring_dir, cookie_context, NULL);
370 if (!g_file_get_contents (path,
375 g_prefix_error (error,
376 _("Error opening keyring `%s' for reading: "),
380 g_assert (contents != NULL);
382 lines = g_strsplit (contents, "\n", 0);
383 for (n = 0; lines[n] != NULL; n++)
385 const gchar *line = lines[n];
394 tokens = g_strsplit (line, " ", 0);
395 if (g_strv_length (tokens) != 3)
400 _("Line %d of the keyring at `%s' with content `%s' is malformed"),
408 line_id = g_ascii_strtoll (tokens[0], &endp, 10);
414 _("First token of line %d of the keyring at `%s' with content `%s' is malformed"),
422 line_when = g_ascii_strtoll (tokens[1], &endp, 10);
428 _("Second token of line %d of the keyring at `%s' with content `%s' is malformed"),
436 if (line_id == cookie_id)
439 ret = tokens[2]; /* steal pointer */
448 /* BOOH, didn't find the cookie */
452 _("Didn't find cookie with id %d in the keyring at `%s'"),
457 g_free (keyring_dir);
464 /* function for logging important events that the system administrator should take notice of */
466 _log (const gchar *message,
472 va_start (var_args, message);
473 s = g_strdup_vprintf (message, var_args);
476 /* TODO: might want to send this to syslog instead */
477 g_printerr ("GDBus-DBUS_COOKIE_SHA1: %s\n", s);
482 keyring_acquire_lock (const gchar *path,
488 guint num_create_tries;
490 g_return_val_if_fail (path != NULL, FALSE);
491 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
494 lock = g_strdup_printf ("%s.lock", path);
496 /* This is what the D-Bus spec says
498 * Create a lockfile name by appending ".lock" to the name of the
499 * cookie file. The server should attempt to create this file using
500 * O_CREAT | O_EXCL. If file creation fails, the lock
501 * fails. Servers should retry for a reasonable period of time,
502 * then they may choose to delete an existing lock to keep users
503 * from having to manually delete a stale lock. [1]
505 * [1] : Lockfiles are used instead of real file locking fcntl() because
506 * real locking implementations are still flaky on network filesystems
509 num_create_tries = 0;
514 while (g_file_test (lock, G_FILE_TEST_EXISTS))
516 /* sleep 10ms, then try again */
521 /* ok, we slept 50*10ms = 0.5 seconds.. Conclude that the lock-file must be
522 * stale (nuke the it from orbit)
524 if (g_unlink (lock) != 0)
528 g_io_error_from_errno (errno),
529 _("Error deleting stale lock-file `%s': %s"),
534 _log ("Deleted stale lock-file `%s'", lock);
539 ret = g_open (lock, O_CREAT |
549 /* EEXIST: pathname already exists and O_CREAT and O_EXCL were used. */
550 if (errno == EEXISTS)
553 if (num_create_tries < 5)
559 g_io_error_from_errno (errno),
560 _("Error creating lock-file `%s': %s"),
572 keyring_release_lock (const gchar *path,
579 g_return_val_if_fail (path != NULL, FALSE);
580 g_return_val_if_fail (lock_fd != -1, FALSE);
581 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
584 lock = g_strdup_printf ("%s.lock", path);
585 if (g_unlink (lock) != 0)
589 g_io_error_from_errno (errno),
590 _("Error unlinking lock-file `%s': %s"),
595 if (close (lock_fd) != 0)
599 g_io_error_from_errno (errno),
600 _("Error closing (unlinked) lock-file `%s': %s"),
614 /* adds an entry to the keyring, taking care of locking and deleting stale/future entries */
616 keyring_generate_entry (const gchar *cookie_context,
628 GString *new_contents;
633 gboolean changed_file;
636 g_return_val_if_fail (cookie_context != NULL, FALSE);
637 g_return_val_if_fail (out_id != NULL, FALSE);
638 g_return_val_if_fail (out_cookie != NULL, FALSE);
639 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
650 keyring_dir = ensure_keyring_directory (error);
651 if (keyring_dir == NULL)
654 path = g_build_filename (keyring_dir, cookie_context, NULL);
656 lock_fd = keyring_acquire_lock (path, error);
662 if (!g_file_get_contents (path,
667 if (local_error->domain == G_FILE_ERROR && local_error->code == G_FILE_ERROR_NOENT)
669 /* file doesn't have to exist */
670 g_error_free (local_error);
674 g_propagate_prefixed_error (error,
676 _("Error opening keyring `%s' for writing: "),
682 new_contents = g_string_new (NULL);
684 changed_file = FALSE;
687 if (contents != NULL)
690 lines = g_strsplit (contents, "\n", 0);
691 for (n = 0; lines[n] != NULL; n++)
693 const gchar *line = lines[n];
703 tokens = g_strsplit (line, " ", 0);
704 if (g_strv_length (tokens) != 3)
709 _("Line %d of the keyring at `%s' with content `%s' is malformed"),
717 line_id = g_ascii_strtoll (tokens[0], &endp, 10);
723 _("First token of line %d of the keyring at `%s' with content `%s' is malformed"),
731 line_when = g_ascii_strtoll (tokens[1], &endp, 10);
737 _("Second token of line %d of the keyring at `%s' with content `%s' is malformed"),
747 * Once the lockfile has been created, the server loads the
748 * cookie file. It should then delete any cookies that are
749 * old (the timeout can be fairly short), or more than a
750 * reasonable time in the future (so that cookies never
751 * accidentally become permanent, if the clock was set far
752 * into the future at some point). If no recent keys remain,
753 * the server may generate a new key.
759 /* Oddball case: entry is more recent than our current wall-clock time..
760 * This is OK, it means that another server on another machine but with
761 * same $HOME wrote the entry.
763 * So discard the entry if it's more than 1 day in the future ("reasonable
764 * time in the future").
766 if (line_when - now > 24*60*60)
769 _log ("Deleted SHA1 cookie from %" G_GUINT64_FORMAT " seconds in the future", line_when - now);
774 /* Discard entry if it's older than 15 minutes ("can be fairly short") */
775 if (now - line_when > 15*60)
783 changed_file = FALSE;
787 g_string_append_printf (new_contents,
788 "%d %" G_GUINT64_FORMAT " %s\n",
792 max_line_id = MAX (line_id, max_line_id);
793 /* Only reuse entry if not older than 10 minutes.
795 * (We need a bit of grace time compared to 15 minutes above.. otherwise
796 * there's a race where we reuse the 14min59.9 secs old entry and a
797 * split-second later another server purges the now 15 minute old entry.)
799 if (now - line_when < 10 * 60)
804 use_cookie = tokens[2]; /* steal memory */
812 } /* for each line */
819 *out_cookie = use_cookie;
825 *out_id = max_line_id + 1;
826 raw_cookie = random_blob (32);
827 *out_cookie = hexencode (raw_cookie, 32);
830 g_string_append_printf (new_contents,
831 "%d %" G_GUINT64_FORMAT " %s\n",
833 (guint64) time (NULL),
838 /* and now actually write the cookie file if there are changes (this is atomic) */
841 if (!g_file_set_contents (path,
848 g_free (*out_cookie);
860 if (!keyring_release_lock (path, lock_fd, &local_error))
866 *error = local_error;
870 g_prefix_error (error,
871 _("(Additionally, releasing the lock for `%s' also failed: %s) "),
873 local_error->message);
878 g_error_free (local_error);
883 g_free (keyring_dir);
887 if (new_contents != NULL)
888 g_string_free (new_contents, TRUE);
893 /* ---------------------------------------------------------------------------------------------------- */
896 generate_sha1 (const gchar *server_challenge,
897 const gchar *client_challenge,
903 str = g_string_new (server_challenge);
904 g_string_append_c (str, ':');
905 g_string_append (str, client_challenge);
906 g_string_append_c (str, ':');
907 g_string_append (str, cookie);
908 sha1 = g_compute_checksum_for_string (G_CHECKSUM_SHA1, str->str, -1);
909 g_string_free (str, TRUE);
914 /* ---------------------------------------------------------------------------------------------------- */
916 static GDBusAuthMechanismState
917 mechanism_server_get_state (GDBusAuthMechanism *mechanism)
919 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
921 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
922 g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
924 return m->priv->state;
928 mechanism_server_initiate (GDBusAuthMechanism *mechanism,
929 const gchar *initial_response,
930 gsize initial_response_len)
932 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
934 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
935 g_return_if_fail (!m->priv->is_server && !m->priv->is_client);
937 m->priv->is_server = TRUE;
938 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
940 if (initial_response != NULL && strlen (initial_response) > 0)
946 uid = g_ascii_strtoll (initial_response, &endp, 10);
949 if (uid == getuid ())
951 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
954 #elif defined(G_OS_WIN32)
955 GCredentials *credentials;
956 credentials = g_credentials_new_for_process ();
957 if (g_strcmp0 (g_credentials_get_windows_user (credentials), initial_response) == 0)
958 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
959 g_object_unref (credentials);
961 #error Please implement for your OS
967 mechanism_server_data_receive (GDBusAuthMechanism *mechanism,
971 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
973 const gchar *client_challenge;
974 const gchar *alleged_sha1;
977 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
978 g_return_if_fail (m->priv->is_server && !m->priv->is_client);
979 g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
984 tokens = g_strsplit (data, " ", 0);
985 if (g_strv_length (tokens) != 2)
987 g_warning ("Malformed data `%s'", data);
988 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
992 client_challenge = tokens[0];
993 alleged_sha1 = tokens[1];
995 sha1 = generate_sha1 (m->priv->server_challenge, client_challenge, m->priv->cookie);
997 if (g_strcmp0 (sha1, alleged_sha1) == 0)
999 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
1003 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1007 g_strfreev (tokens);
1012 mechanism_server_data_send (GDBusAuthMechanism *mechanism,
1013 gsize *out_data_len)
1015 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1018 const gchar *cookie_context;
1021 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1022 g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
1023 g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
1027 /* TODO: use GDBusAuthObserver here to get the cookie context to use? */
1028 cookie_context = "org_gtk_gdbus_general";
1031 if (!keyring_generate_entry (cookie_context,
1036 g_warning ("Error adding entry to keyring: %s", error->message);
1037 g_error_free (error);
1038 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1042 m->priv->server_challenge = random_ascii_string (16);
1043 s = g_strdup_printf ("%s %d %s",
1046 m->priv->server_challenge);
1048 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
1055 mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism)
1057 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1059 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1060 g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
1061 g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
1063 /* can never end up here because we are never in the REJECTED state */
1064 g_assert_not_reached ();
1070 mechanism_server_shutdown (GDBusAuthMechanism *mechanism)
1072 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1074 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1075 g_return_if_fail (m->priv->is_server && !m->priv->is_client);
1077 m->priv->is_server = FALSE;
1080 /* ---------------------------------------------------------------------------------------------------- */
1082 static GDBusAuthMechanismState
1083 mechanism_client_get_state (GDBusAuthMechanism *mechanism)
1085 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1087 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
1088 g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
1090 return m->priv->state;
1094 mechanism_client_initiate (GDBusAuthMechanism *mechanism,
1095 gsize *out_initial_response_len)
1097 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1098 gchar *initial_response;
1100 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1101 g_return_val_if_fail (!m->priv->is_server && !m->priv->is_client, NULL);
1103 m->priv->is_client = TRUE;
1104 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
1106 *out_initial_response_len = -1;
1109 initial_response = g_strdup_printf ("%" G_GINT64_FORMAT, (gint64) getuid ());
1110 #elif defined (G_OS_WIN32)
1112 GCredentials *credentials;
1113 credentials = g_credentials_new_for_process ();
1114 initial_response = g_strdup (g_credentials_get_windows_user (credentials));
1115 g_object_unref (credentials);
1119 g_assert (initial_response != NULL);
1121 return initial_response;
1125 mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
1129 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1131 const gchar *cookie_context;
1133 const gchar *server_challenge;
1134 gchar *client_challenge;
1140 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1141 g_return_if_fail (m->priv->is_client && !m->priv->is_server);
1142 g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
1146 client_challenge = NULL;
1148 tokens = g_strsplit (data, " ", 0);
1149 if (g_strv_length (tokens) != 3)
1151 g_warning ("Malformed data `%s'", data);
1152 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1156 cookie_context = tokens[0];
1157 cookie_id = g_ascii_strtoll (tokens[1], &endp, 10);
1160 g_warning ("Malformed cookie_id `%s'", tokens[1]);
1161 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1164 server_challenge = tokens[2];
1167 cookie = keyring_lookup_entry (cookie_context, cookie_id, &error);
1170 g_warning ("Problems looking up entry in keyring: %s", error->message);
1171 g_error_free (error);
1172 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
1176 client_challenge = random_ascii_string (16);
1177 sha1 = generate_sha1 (server_challenge, client_challenge, cookie);
1178 m->priv->to_send = g_strdup_printf ("%s %s", client_challenge, sha1);
1180 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
1183 g_strfreev (tokens);
1185 g_free (client_challenge);
1189 mechanism_client_data_send (GDBusAuthMechanism *mechanism,
1190 gsize *out_data_len)
1192 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1194 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
1195 g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, NULL);
1196 g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
1198 g_assert (m->priv->to_send != NULL);
1200 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
1202 return g_strdup (m->priv->to_send);
1206 mechanism_client_shutdown (GDBusAuthMechanism *mechanism)
1208 GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
1210 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism));
1211 g_return_if_fail (m->priv->is_client && !m->priv->is_server);
1213 m->priv->is_client = FALSE;
1216 /* ---------------------------------------------------------------------------------------------------- */