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 #pragma GCC diagnostic push
284 #pragma GCC diagnostic warning "-Wcpp"
285 #warning Please implement permission checking on this non-UNIX platform
286 #pragma GCC diagnostic pop
293 if (g_mkdir (path
, 0700) != 0)
298 g_io_error_from_errno (errsv
),
299 _("Error creating directory “%s”: %s"),
311 /* ---------------------------------------------------------------------------------------------------- */
313 /* looks up an entry in the keyring */
315 keyring_lookup_entry (const gchar
*cookie_context
,
326 g_return_val_if_fail (cookie_context
!= NULL
, NULL
);
327 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
334 keyring_dir
= ensure_keyring_directory (error
);
335 if (keyring_dir
== NULL
)
338 path
= g_build_filename (keyring_dir
, cookie_context
, NULL
);
340 if (!g_file_get_contents (path
,
345 g_prefix_error (error
,
346 _("Error opening keyring “%s” for reading: "),
350 g_assert (contents
!= NULL
);
352 lines
= g_strsplit (contents
, "\n", 0);
353 for (n
= 0; lines
[n
] != NULL
; n
++)
355 const gchar
*line
= lines
[n
];
363 tokens
= g_strsplit (line
, " ", 0);
364 if (g_strv_length (tokens
) != 3)
369 _("Line %d of the keyring at “%s” with content “%s” is malformed"),
377 line_id
= g_ascii_strtoll (tokens
[0], &endp
, 10);
383 _("First token of line %d of the keyring at “%s” with content “%s” is malformed"),
391 (void)g_ascii_strtoll (tokens
[1], &endp
, 10); /* do not care what the timestamp is */
397 _("Second token of line %d of the keyring at “%s” with content “%s” is malformed"),
405 if (line_id
== cookie_id
)
408 ret
= tokens
[2]; /* steal pointer */
417 /* BOOH, didn't find the cookie */
421 _("Didn’t find cookie with id %d in the keyring at “%s”"),
426 g_free (keyring_dir
);
433 /* function for logging important events that the system administrator should take notice of */
436 _log (const gchar
*message
,
442 va_start (var_args
, message
);
443 s
= g_strdup_vprintf (message
, var_args
);
446 /* TODO: might want to send this to syslog instead */
447 g_printerr ("GDBus-DBUS_COOKIE_SHA1: %s\n", s
);
452 keyring_acquire_lock (const gchar
*path
,
459 guint num_create_tries
;
463 g_return_val_if_fail (path
!= NULL
, FALSE
);
464 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
467 lock
= g_strdup_printf ("%s.lock", path
);
469 /* This is what the D-Bus spec says
471 * Create a lockfile name by appending ".lock" to the name of the
472 * cookie file. The server should attempt to create this file using
473 * O_CREAT | O_EXCL. If file creation fails, the lock
474 * fails. Servers should retry for a reasonable period of time,
475 * then they may choose to delete an existing lock to keep users
476 * from having to manually delete a stale lock. [1]
478 * [1] : Lockfiles are used instead of real file locking fcntl() because
479 * real locking implementations are still flaky on network filesystems
483 num_create_tries
= 0;
487 while (g_file_test (lock
, G_FILE_TEST_EXISTS
))
489 /* sleep 10ms, then try again */
494 /* ok, we slept 50*10ms = 0.5 seconds. Conclude that the lock file must be
495 * stale (nuke the it from orbit)
497 if (g_unlink (lock
) != 0)
502 g_io_error_from_errno (errsv
),
503 _("Error deleting stale lock file “%s”: %s"),
508 _log ("Deleted stale lock file '%s'", lock
);
513 ret
= g_open (lock
, O_CREAT
|
524 /* EEXIST: pathname already exists and O_CREAT and O_EXCL were used. */
525 if (errsv
== EEXISTS
)
528 if (num_create_tries
< 5)
534 g_io_error_from_errno (errsv
),
535 _("Error creating lock file “%s”: %s"),
547 keyring_release_lock (const gchar
*path
,
554 g_return_val_if_fail (path
!= NULL
, FALSE
);
555 g_return_val_if_fail (lock_fd
!= -1, FALSE
);
556 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
559 lock
= g_strdup_printf ("%s.lock", path
);
560 if (close (lock_fd
) != 0)
565 g_io_error_from_errno (errsv
),
566 _("Error closing (unlinked) lock file “%s”: %s"),
571 if (g_unlink (lock
) != 0)
576 g_io_error_from_errno (errsv
),
577 _("Error unlinking lock file “%s”: %s"),
591 /* adds an entry to the keyring, taking care of locking and deleting stale/future entries */
593 keyring_generate_entry (const gchar
*cookie_context
,
605 GString
*new_contents
;
610 gboolean changed_file
;
613 g_return_val_if_fail (cookie_context
!= NULL
, FALSE
);
614 g_return_val_if_fail (out_id
!= NULL
, FALSE
);
615 g_return_val_if_fail (out_cookie
!= NULL
, FALSE
);
616 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
628 keyring_dir
= ensure_keyring_directory (error
);
629 if (keyring_dir
== NULL
)
632 path
= g_build_filename (keyring_dir
, cookie_context
, NULL
);
634 lock_fd
= keyring_acquire_lock (path
, error
);
640 if (!g_file_get_contents (path
,
645 if (local_error
->domain
== G_FILE_ERROR
&& local_error
->code
== G_FILE_ERROR_NOENT
)
647 /* file doesn't have to exist */
648 g_error_free (local_error
);
652 g_propagate_prefixed_error (error
,
654 _("Error opening keyring “%s” for writing: "),
660 new_contents
= g_string_new (NULL
);
661 now
= g_get_real_time () / G_USEC_PER_SEC
;
662 changed_file
= FALSE
;
665 if (contents
!= NULL
)
668 lines
= g_strsplit (contents
, "\n", 0);
669 for (n
= 0; lines
[n
] != NULL
; n
++)
671 const gchar
*line
= lines
[n
];
681 tokens
= g_strsplit (line
, " ", 0);
682 if (g_strv_length (tokens
) != 3)
687 _("Line %d of the keyring at “%s” with content “%s” is malformed"),
695 line_id
= g_ascii_strtoll (tokens
[0], &endp
, 10);
701 _("First token of line %d of the keyring at “%s” with content “%s” is malformed"),
709 line_when
= g_ascii_strtoll (tokens
[1], &endp
, 10);
715 _("Second token of line %d of the keyring at “%s” with content “%s” is malformed"),
726 * Once the lockfile has been created, the server loads the
727 * cookie file. It should then delete any cookies that are
728 * old (the timeout can be fairly short), or more than a
729 * reasonable time in the future (so that cookies never
730 * accidentally become permanent, if the clock was set far
731 * into the future at some point). If no recent keys remain,
732 * the server may generate a new key.
738 /* Oddball case: entry is more recent than our current wall-clock time..
739 * This is OK, it means that another server on another machine but with
740 * same $HOME wrote the entry.
742 * So discard the entry if it's more than 1 day in the future ("reasonable
743 * time in the future").
745 if (line_when
- now
> 24*60*60)
748 _log ("Deleted SHA1 cookie from %" G_GUINT64_FORMAT
" seconds in the future", line_when
- now
);
753 /* Discard entry if it's older than 15 minutes ("can be fairly short") */
754 if (now
- line_when
> 15*60)
762 changed_file
= FALSE
;
766 g_string_append_printf (new_contents
,
767 "%d %" G_GUINT64_FORMAT
" %s\n",
771 max_line_id
= MAX (line_id
, max_line_id
);
772 /* Only reuse entry if not older than 10 minutes.
774 * (We need a bit of grace time compared to 15 minutes above.. otherwise
775 * there's a race where we reuse the 14min59.9 secs old entry and a
776 * split-second later another server purges the now 15 minute old entry.)
778 if (now
- line_when
< 10 * 60)
783 use_cookie
= tokens
[2]; /* steal memory */
791 } /* for each line */
798 *out_cookie
= use_cookie
;
804 *out_id
= max_line_id
+ 1;
805 raw_cookie
= random_blob (32);
806 *out_cookie
= _g_dbus_hexencode (raw_cookie
, 32);
809 g_string_append_printf (new_contents
,
810 "%d %" G_GINT64_FORMAT
" %s\n",
812 g_get_real_time () / G_USEC_PER_SEC
,
817 /* and now actually write the cookie file if there are changes (this is atomic) */
820 if (!g_file_set_contents (path
,
827 g_free (*out_cookie
);
839 if (!keyring_release_lock (path
, lock_fd
, &local_error
))
845 *error
= local_error
;
849 g_prefix_error (error
,
850 _("(Additionally, releasing the lock for “%s” also failed: %s) "),
852 local_error
->message
);
857 g_error_free (local_error
);
862 g_free (keyring_dir
);
866 if (new_contents
!= NULL
)
867 g_string_free (new_contents
, TRUE
);
872 /* ---------------------------------------------------------------------------------------------------- */
875 generate_sha1 (const gchar
*server_challenge
,
876 const gchar
*client_challenge
,
882 str
= g_string_new (server_challenge
);
883 g_string_append_c (str
, ':');
884 g_string_append (str
, client_challenge
);
885 g_string_append_c (str
, ':');
886 g_string_append (str
, cookie
);
887 sha1
= g_compute_checksum_for_string (G_CHECKSUM_SHA1
, str
->str
, -1);
888 g_string_free (str
, TRUE
);
893 /* ---------------------------------------------------------------------------------------------------- */
895 static GDBusAuthMechanismState
896 mechanism_server_get_state (GDBusAuthMechanism
*mechanism
)
898 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
900 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), G_DBUS_AUTH_MECHANISM_STATE_INVALID
);
901 g_return_val_if_fail (m
->priv
->is_server
&& !m
->priv
->is_client
, G_DBUS_AUTH_MECHANISM_STATE_INVALID
);
903 return m
->priv
->state
;
907 mechanism_server_initiate (GDBusAuthMechanism
*mechanism
,
908 const gchar
*initial_response
,
909 gsize initial_response_len
)
911 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
913 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
));
914 g_return_if_fail (!m
->priv
->is_server
&& !m
->priv
->is_client
);
916 m
->priv
->is_server
= TRUE
;
917 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
919 if (initial_response
!= NULL
&& initial_response_len
> 0)
925 uid
= g_ascii_strtoll (initial_response
, &endp
, 10);
928 if (uid
== getuid ())
930 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND
;
933 #elif defined(G_OS_WIN32)
935 sid
= _g_dbus_win32_get_user_sid ();
936 if (g_strcmp0 (initial_response
, sid
) == 0)
937 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND
;
940 #error Please implement for your OS
946 mechanism_server_data_receive (GDBusAuthMechanism
*mechanism
,
950 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
952 const gchar
*client_challenge
;
953 const gchar
*alleged_sha1
;
956 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
));
957 g_return_if_fail (m
->priv
->is_server
&& !m
->priv
->is_client
);
958 g_return_if_fail (m
->priv
->state
== G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA
);
963 tokens
= g_strsplit (data
, " ", 0);
964 if (g_strv_length (tokens
) != 2)
966 g_warning ("Malformed data '%s'", data
);
967 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
971 client_challenge
= tokens
[0];
972 alleged_sha1
= tokens
[1];
974 sha1
= generate_sha1 (m
->priv
->server_challenge
, client_challenge
, m
->priv
->cookie
);
976 if (g_strcmp0 (sha1
, alleged_sha1
) == 0)
978 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED
;
982 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
991 mechanism_server_data_send (GDBusAuthMechanism
*mechanism
,
994 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
997 const gchar
*cookie_context
;
1000 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), NULL
);
1001 g_return_val_if_fail (m
->priv
->is_server
&& !m
->priv
->is_client
, NULL
);
1002 g_return_val_if_fail (m
->priv
->state
== G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND
, NULL
);
1007 /* TODO: use GDBusAuthObserver here to get the cookie context to use? */
1008 cookie_context
= "org_gtk_gdbus_general";
1012 if (!keyring_generate_entry (cookie_context
,
1017 g_warning ("Error adding entry to keyring: %s", error
->message
);
1018 g_error_free (error
);
1019 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
1023 m
->priv
->server_challenge
= random_ascii_string (16);
1024 s
= g_strdup_printf ("%s %d %s",
1027 m
->priv
->server_challenge
);
1028 *out_data_len
= strlen (s
);
1030 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA
;
1037 mechanism_server_get_reject_reason (GDBusAuthMechanism
*mechanism
)
1039 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1041 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), NULL
);
1042 g_return_val_if_fail (m
->priv
->is_server
&& !m
->priv
->is_client
, NULL
);
1043 g_return_val_if_fail (m
->priv
->state
== G_DBUS_AUTH_MECHANISM_STATE_REJECTED
, NULL
);
1045 /* can never end up here because we are never in the REJECTED state */
1046 g_assert_not_reached ();
1052 mechanism_server_shutdown (GDBusAuthMechanism
*mechanism
)
1054 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1056 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
));
1057 g_return_if_fail (m
->priv
->is_server
&& !m
->priv
->is_client
);
1059 m
->priv
->is_server
= FALSE
;
1062 /* ---------------------------------------------------------------------------------------------------- */
1064 static GDBusAuthMechanismState
1065 mechanism_client_get_state (GDBusAuthMechanism
*mechanism
)
1067 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1069 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), G_DBUS_AUTH_MECHANISM_STATE_INVALID
);
1070 g_return_val_if_fail (m
->priv
->is_client
&& !m
->priv
->is_server
, G_DBUS_AUTH_MECHANISM_STATE_INVALID
);
1072 return m
->priv
->state
;
1076 mechanism_client_initiate (GDBusAuthMechanism
*mechanism
,
1077 gsize
*out_initial_response_len
)
1079 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1080 gchar
*initial_response
;
1082 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), NULL
);
1083 g_return_val_if_fail (!m
->priv
->is_server
&& !m
->priv
->is_client
, NULL
);
1085 m
->priv
->is_client
= TRUE
;
1086 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA
;
1088 *out_initial_response_len
= 0;
1091 initial_response
= g_strdup_printf ("%" G_GINT64_FORMAT
, (gint64
) getuid ());
1092 *out_initial_response_len
= strlen (initial_response
);
1093 #elif defined (G_OS_WIN32)
1094 initial_response
= _g_dbus_win32_get_user_sid ();
1095 *out_initial_response_len
= strlen (initial_response
);
1097 #error Please implement for your OS
1099 g_assert (initial_response
!= NULL
);
1101 return initial_response
;
1105 mechanism_client_data_receive (GDBusAuthMechanism
*mechanism
,
1109 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1111 const gchar
*cookie_context
;
1113 const gchar
*server_challenge
;
1114 gchar
*client_challenge
;
1120 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
));
1121 g_return_if_fail (m
->priv
->is_client
&& !m
->priv
->is_server
);
1122 g_return_if_fail (m
->priv
->state
== G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA
);
1126 client_challenge
= NULL
;
1128 tokens
= g_strsplit (data
, " ", 0);
1129 if (g_strv_length (tokens
) != 3)
1131 g_warning ("Malformed data '%s'", data
);
1132 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
1136 cookie_context
= tokens
[0];
1137 cookie_id
= g_ascii_strtoll (tokens
[1], &endp
, 10);
1140 g_warning ("Malformed cookie_id '%s'", tokens
[1]);
1141 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
1144 server_challenge
= tokens
[2];
1147 cookie
= keyring_lookup_entry (cookie_context
, cookie_id
, &error
);
1150 g_warning ("Problems looking up entry in keyring: %s", error
->message
);
1151 g_error_free (error
);
1152 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
1156 client_challenge
= random_ascii_string (16);
1157 sha1
= generate_sha1 (server_challenge
, client_challenge
, cookie
);
1158 m
->priv
->to_send
= g_strdup_printf ("%s %s", client_challenge
, sha1
);
1160 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND
;
1163 g_strfreev (tokens
);
1165 g_free (client_challenge
);
1169 mechanism_client_data_send (GDBusAuthMechanism
*mechanism
,
1170 gsize
*out_data_len
)
1172 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1174 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), NULL
);
1175 g_return_val_if_fail (m
->priv
->is_client
&& !m
->priv
->is_server
, NULL
);
1176 g_return_val_if_fail (m
->priv
->state
== G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND
, NULL
);
1178 g_assert (m
->priv
->to_send
!= NULL
);
1180 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED
;
1182 *out_data_len
= strlen (m
->priv
->to_send
);
1183 return g_strdup (m
->priv
->to_send
);
1187 mechanism_client_shutdown (GDBusAuthMechanism
*mechanism
)
1189 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1191 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
));
1192 g_return_if_fail (m
->priv
->is_client
&& !m
->priv
->is_server
);
1194 m
->priv
->is_client
= FALSE
;
1197 /* ---------------------------------------------------------------------------------------------------- */