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 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>
28 #include <sys/types.h>
36 #include <glib/gstdio.h>
38 #include "gdbusauthmechanismsha1.h"
39 #include "gcredentials.h"
40 #include "gdbuserror.h"
41 #include "gioenumtypes.h"
43 #include "gdbusprivate.h"
47 struct _GDBusAuthMechanismSha1Private
51 GDBusAuthMechanismState state
;
53 /* used on the client side */
56 /* used on the server side */
58 gchar
*server_challenge
;
61 static gint
mechanism_get_priority (void);
62 static const gchar
*mechanism_get_name (void);
64 static gboolean
mechanism_is_supported (GDBusAuthMechanism
*mechanism
);
65 static gchar
*mechanism_encode_data (GDBusAuthMechanism
*mechanism
,
69 static gchar
*mechanism_decode_data (GDBusAuthMechanism
*mechanism
,
73 static GDBusAuthMechanismState
mechanism_server_get_state (GDBusAuthMechanism
*mechanism
);
74 static void mechanism_server_initiate (GDBusAuthMechanism
*mechanism
,
75 const gchar
*initial_response
,
76 gsize initial_response_len
);
77 static void mechanism_server_data_receive (GDBusAuthMechanism
*mechanism
,
80 static gchar
*mechanism_server_data_send (GDBusAuthMechanism
*mechanism
,
82 static gchar
*mechanism_server_get_reject_reason (GDBusAuthMechanism
*mechanism
);
83 static void mechanism_server_shutdown (GDBusAuthMechanism
*mechanism
);
84 static GDBusAuthMechanismState
mechanism_client_get_state (GDBusAuthMechanism
*mechanism
);
85 static gchar
*mechanism_client_initiate (GDBusAuthMechanism
*mechanism
,
86 gsize
*out_initial_response_len
);
87 static void mechanism_client_data_receive (GDBusAuthMechanism
*mechanism
,
90 static gchar
*mechanism_client_data_send (GDBusAuthMechanism
*mechanism
,
92 static void mechanism_client_shutdown (GDBusAuthMechanism
*mechanism
);
94 /* ---------------------------------------------------------------------------------------------------- */
96 G_DEFINE_TYPE (GDBusAuthMechanismSha1
, _g_dbus_auth_mechanism_sha1
, G_TYPE_DBUS_AUTH_MECHANISM
);
98 /* ---------------------------------------------------------------------------------------------------- */
101 _g_dbus_auth_mechanism_sha1_finalize (GObject
*object
)
103 GDBusAuthMechanismSha1
*mechanism
= G_DBUS_AUTH_MECHANISM_SHA1 (object
);
105 g_free (mechanism
->priv
->to_send
);
107 g_free (mechanism
->priv
->cookie
);
108 g_free (mechanism
->priv
->server_challenge
);
110 if (G_OBJECT_CLASS (_g_dbus_auth_mechanism_sha1_parent_class
)->finalize
!= NULL
)
111 G_OBJECT_CLASS (_g_dbus_auth_mechanism_sha1_parent_class
)->finalize (object
);
115 _g_dbus_auth_mechanism_sha1_class_init (GDBusAuthMechanismSha1Class
*klass
)
117 GObjectClass
*gobject_class
;
118 GDBusAuthMechanismClass
*mechanism_class
;
120 g_type_class_add_private (klass
, sizeof (GDBusAuthMechanismSha1Private
));
122 gobject_class
= G_OBJECT_CLASS (klass
);
123 gobject_class
->finalize
= _g_dbus_auth_mechanism_sha1_finalize
;
125 mechanism_class
= G_DBUS_AUTH_MECHANISM_CLASS (klass
);
126 mechanism_class
->get_priority
= mechanism_get_priority
;
127 mechanism_class
->get_name
= mechanism_get_name
;
128 mechanism_class
->is_supported
= mechanism_is_supported
;
129 mechanism_class
->encode_data
= mechanism_encode_data
;
130 mechanism_class
->decode_data
= mechanism_decode_data
;
131 mechanism_class
->server_get_state
= mechanism_server_get_state
;
132 mechanism_class
->server_initiate
= mechanism_server_initiate
;
133 mechanism_class
->server_data_receive
= mechanism_server_data_receive
;
134 mechanism_class
->server_data_send
= mechanism_server_data_send
;
135 mechanism_class
->server_get_reject_reason
= mechanism_server_get_reject_reason
;
136 mechanism_class
->server_shutdown
= mechanism_server_shutdown
;
137 mechanism_class
->client_get_state
= mechanism_client_get_state
;
138 mechanism_class
->client_initiate
= mechanism_client_initiate
;
139 mechanism_class
->client_data_receive
= mechanism_client_data_receive
;
140 mechanism_class
->client_data_send
= mechanism_client_data_send
;
141 mechanism_class
->client_shutdown
= mechanism_client_shutdown
;
145 _g_dbus_auth_mechanism_sha1_init (GDBusAuthMechanismSha1
*mechanism
)
147 mechanism
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (mechanism
,
148 G_TYPE_DBUS_AUTH_MECHANISM_SHA1
,
149 GDBusAuthMechanismSha1Private
);
152 /* ---------------------------------------------------------------------------------------------------- */
155 mechanism_get_priority (void)
161 mechanism_get_name (void)
163 return "DBUS_COOKIE_SHA1";
167 mechanism_is_supported (GDBusAuthMechanism
*mechanism
)
169 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), FALSE
);
174 mechanism_encode_data (GDBusAuthMechanism
*mechanism
,
184 mechanism_decode_data (GDBusAuthMechanism
*mechanism
,
192 /* ---------------------------------------------------------------------------------------------------- */
198 ret
= g_random_int_range (0, 60);
209 random_ascii_string (guint len
)
214 challenge
= g_string_new (NULL
);
215 for (n
= 0; n
< len
; n
++)
216 g_string_append_c (challenge
, random_ascii ());
217 return g_string_free (challenge
, FALSE
);
221 random_blob (guint len
)
226 challenge
= g_string_new (NULL
);
227 for (n
= 0; n
< len
; n
++)
228 g_string_append_c (challenge
, g_random_int_range (0, 256));
229 return g_string_free (challenge
, FALSE
);
232 /* ---------------------------------------------------------------------------------------------------- */
234 /* ensure keyring dir exists and permissions are correct */
236 ensure_keyring_directory (GError
**error
)
241 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
243 e
= g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR");
250 path
= g_build_filename (g_get_home_dir (),
255 if (g_file_test (path
, G_FILE_TEST_EXISTS
| G_FILE_TEST_IS_DIR
))
257 if (g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION") == NULL
)
261 if (stat (path
, &statbuf
) != 0)
265 g_io_error_from_errno (errno
),
266 _("Error when getting information for directory `%s': %s"),
273 if ((statbuf
.st_mode
& 0777) != 0700)
278 _("Permissions on directory `%s' are malformed. Expected mode 0700, got 0%o"),
280 statbuf
.st_mode
& 0777);
287 #warning Please implement permission checking on this non-UNIX platform
294 if (g_mkdir (path
, 0700) != 0)
298 g_io_error_from_errno (errno
),
299 _("Error creating directory `%s': %s"),
311 /* ---------------------------------------------------------------------------------------------------- */
314 append_nibble (GString
*s
, gint val
)
316 g_string_append_c (s
, val
>= 10 ? ('a' + val
- 10) : ('0' + val
));
320 hexencode (const gchar
*str
,
329 s
= g_string_new (NULL
);
330 for (n
= 0; n
< len
; n
++)
336 val
= ((const guchar
*) str
)[n
];
337 upper_nibble
= val
>> 4;
338 lower_nibble
= val
& 0x0f;
340 append_nibble (s
, upper_nibble
);
341 append_nibble (s
, lower_nibble
);
344 return g_string_free (s
, FALSE
);
347 /* ---------------------------------------------------------------------------------------------------- */
349 /* looks up an entry in the keyring */
351 keyring_lookup_entry (const gchar
*cookie_context
,
362 g_return_val_if_fail (cookie_context
!= NULL
, NULL
);
363 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
370 keyring_dir
= ensure_keyring_directory (error
);
371 if (keyring_dir
== NULL
)
374 path
= g_build_filename (keyring_dir
, cookie_context
, NULL
);
376 if (!g_file_get_contents (path
,
381 g_prefix_error (error
,
382 _("Error opening keyring `%s' for reading: "),
386 g_assert (contents
!= NULL
);
388 lines
= g_strsplit (contents
, "\n", 0);
389 for (n
= 0; lines
[n
] != NULL
; n
++)
391 const gchar
*line
= lines
[n
];
400 tokens
= g_strsplit (line
, " ", 0);
401 if (g_strv_length (tokens
) != 3)
406 _("Line %d of the keyring at `%s' with content `%s' is malformed"),
414 line_id
= g_ascii_strtoll (tokens
[0], &endp
, 10);
420 _("First token of line %d of the keyring at `%s' with content `%s' is malformed"),
428 line_when
= g_ascii_strtoll (tokens
[1], &endp
, 10);
429 line_when
= line_when
; /* To avoid -Wunused-but-set-variable */
435 _("Second token of line %d of the keyring at `%s' with content `%s' is malformed"),
443 if (line_id
== cookie_id
)
446 ret
= tokens
[2]; /* steal pointer */
455 /* BOOH, didn't find the cookie */
459 _("Didn't find cookie with id %d in the keyring at `%s'"),
464 g_free (keyring_dir
);
471 /* function for logging important events that the system administrator should take notice of */
473 _log (const gchar
*message
,
479 va_start (var_args
, message
);
480 s
= g_strdup_vprintf (message
, var_args
);
483 /* TODO: might want to send this to syslog instead */
484 g_printerr ("GDBus-DBUS_COOKIE_SHA1: %s\n", s
);
489 keyring_acquire_lock (const gchar
*path
,
495 guint num_create_tries
;
497 g_return_val_if_fail (path
!= NULL
, FALSE
);
498 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
501 lock
= g_strdup_printf ("%s.lock", path
);
503 /* This is what the D-Bus spec says
505 * Create a lockfile name by appending ".lock" to the name of the
506 * cookie file. The server should attempt to create this file using
507 * O_CREAT | O_EXCL. If file creation fails, the lock
508 * fails. Servers should retry for a reasonable period of time,
509 * then they may choose to delete an existing lock to keep users
510 * from having to manually delete a stale lock. [1]
512 * [1] : Lockfiles are used instead of real file locking fcntl() because
513 * real locking implementations are still flaky on network filesystems
516 num_create_tries
= 0;
521 while (g_file_test (lock
, G_FILE_TEST_EXISTS
))
523 /* sleep 10ms, then try again */
528 /* ok, we slept 50*10ms = 0.5 seconds. Conclude that the lock file must be
529 * stale (nuke the it from orbit)
531 if (g_unlink (lock
) != 0)
535 g_io_error_from_errno (errno
),
536 _("Error deleting stale lock file `%s': %s"),
541 _log ("Deleted stale lock file `%s'", lock
);
546 ret
= g_open (lock
, O_CREAT
|
556 /* EEXIST: pathname already exists and O_CREAT and O_EXCL were used. */
557 if (errno
== EEXISTS
)
560 if (num_create_tries
< 5)
564 num_create_tries
= num_create_tries
; /* To avoid -Wunused-but-set-variable */
567 g_io_error_from_errno (errno
),
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)
597 g_io_error_from_errno (errno
),
598 _("Error closing (unlinked) lock file `%s': %s"),
603 if (g_unlink (lock
) != 0)
607 g_io_error_from_errno (errno
),
608 _("Error unlinking lock file `%s': %s"),
622 /* adds an entry to the keyring, taking care of locking and deleting stale/future entries */
624 keyring_generate_entry (const gchar
*cookie_context
,
636 GString
*new_contents
;
641 gboolean changed_file
;
644 g_return_val_if_fail (cookie_context
!= NULL
, FALSE
);
645 g_return_val_if_fail (out_id
!= NULL
, FALSE
);
646 g_return_val_if_fail (out_cookie
!= NULL
, FALSE
);
647 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
659 keyring_dir
= ensure_keyring_directory (error
);
660 if (keyring_dir
== NULL
)
663 path
= g_build_filename (keyring_dir
, cookie_context
, NULL
);
665 lock_fd
= keyring_acquire_lock (path
, error
);
671 if (!g_file_get_contents (path
,
676 if (local_error
->domain
== G_FILE_ERROR
&& local_error
->code
== G_FILE_ERROR_NOENT
)
678 /* file doesn't have to exist */
679 g_error_free (local_error
);
683 g_propagate_prefixed_error (error
,
685 _("Error opening keyring `%s' for writing: "),
691 new_contents
= g_string_new (NULL
);
693 changed_file
= FALSE
;
696 if (contents
!= NULL
)
699 lines
= g_strsplit (contents
, "\n", 0);
700 for (n
= 0; lines
[n
] != NULL
; n
++)
702 const gchar
*line
= lines
[n
];
712 tokens
= g_strsplit (line
, " ", 0);
713 if (g_strv_length (tokens
) != 3)
718 _("Line %d of the keyring at `%s' with content `%s' is malformed"),
726 line_id
= g_ascii_strtoll (tokens
[0], &endp
, 10);
732 _("First token of line %d of the keyring at `%s' with content `%s' is malformed"),
740 line_when
= g_ascii_strtoll (tokens
[1], &endp
, 10);
746 _("Second token of line %d of the keyring at `%s' with content `%s' is malformed"),
753 line_when
= line_when
; /* To avoid -Wunused-but-set-variable */
758 * Once the lockfile has been created, the server loads the
759 * cookie file. It should then delete any cookies that are
760 * old (the timeout can be fairly short), or more than a
761 * reasonable time in the future (so that cookies never
762 * accidentally become permanent, if the clock was set far
763 * into the future at some point). If no recent keys remain,
764 * the server may generate a new key.
770 /* Oddball case: entry is more recent than our current wall-clock time..
771 * This is OK, it means that another server on another machine but with
772 * same $HOME wrote the entry.
774 * So discard the entry if it's more than 1 day in the future ("reasonable
775 * time in the future").
777 if (line_when
- now
> 24*60*60)
780 _log ("Deleted SHA1 cookie from %" G_GUINT64_FORMAT
" seconds in the future", line_when
- now
);
785 /* Discard entry if it's older than 15 minutes ("can be fairly short") */
786 if (now
- line_when
> 15*60)
794 changed_file
= FALSE
;
798 g_string_append_printf (new_contents
,
799 "%d %" G_GUINT64_FORMAT
" %s\n",
803 max_line_id
= MAX (line_id
, max_line_id
);
804 /* Only reuse entry if not older than 10 minutes.
806 * (We need a bit of grace time compared to 15 minutes above.. otherwise
807 * there's a race where we reuse the 14min59.9 secs old entry and a
808 * split-second later another server purges the now 15 minute old entry.)
810 if (now
- line_when
< 10 * 60)
815 use_cookie
= tokens
[2]; /* steal memory */
823 } /* for each line */
830 *out_cookie
= use_cookie
;
836 *out_id
= max_line_id
+ 1;
837 raw_cookie
= random_blob (32);
838 *out_cookie
= hexencode (raw_cookie
, 32);
841 g_string_append_printf (new_contents
,
842 "%d %" G_GUINT64_FORMAT
" %s\n",
844 (guint64
) time (NULL
),
849 /* and now actually write the cookie file if there are changes (this is atomic) */
852 if (!g_file_set_contents (path
,
859 g_free (*out_cookie
);
871 if (!keyring_release_lock (path
, lock_fd
, &local_error
))
877 *error
= local_error
;
881 g_prefix_error (error
,
882 _("(Additionally, releasing the lock for `%s' also failed: %s) "),
884 local_error
->message
);
889 g_error_free (local_error
);
894 g_free (keyring_dir
);
898 if (new_contents
!= NULL
)
899 g_string_free (new_contents
, TRUE
);
904 /* ---------------------------------------------------------------------------------------------------- */
907 generate_sha1 (const gchar
*server_challenge
,
908 const gchar
*client_challenge
,
914 str
= g_string_new (server_challenge
);
915 g_string_append_c (str
, ':');
916 g_string_append (str
, client_challenge
);
917 g_string_append_c (str
, ':');
918 g_string_append (str
, cookie
);
919 sha1
= g_compute_checksum_for_string (G_CHECKSUM_SHA1
, str
->str
, -1);
920 g_string_free (str
, TRUE
);
925 /* ---------------------------------------------------------------------------------------------------- */
927 static GDBusAuthMechanismState
928 mechanism_server_get_state (GDBusAuthMechanism
*mechanism
)
930 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
932 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), G_DBUS_AUTH_MECHANISM_STATE_INVALID
);
933 g_return_val_if_fail (m
->priv
->is_server
&& !m
->priv
->is_client
, G_DBUS_AUTH_MECHANISM_STATE_INVALID
);
935 return m
->priv
->state
;
939 mechanism_server_initiate (GDBusAuthMechanism
*mechanism
,
940 const gchar
*initial_response
,
941 gsize initial_response_len
)
943 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
945 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
));
946 g_return_if_fail (!m
->priv
->is_server
&& !m
->priv
->is_client
);
948 m
->priv
->is_server
= TRUE
;
949 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
951 if (initial_response
!= NULL
&& strlen (initial_response
) > 0)
957 uid
= g_ascii_strtoll (initial_response
, &endp
, 10);
960 if (uid
== getuid ())
962 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND
;
965 #elif defined(G_OS_WIN32)
967 sid
= _g_dbus_win32_get_user_sid ();
968 if (g_strcmp0 (initial_response
, sid
) == 0)
969 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND
;
972 #error Please implement for your OS
978 mechanism_server_data_receive (GDBusAuthMechanism
*mechanism
,
982 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
984 const gchar
*client_challenge
;
985 const gchar
*alleged_sha1
;
988 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
));
989 g_return_if_fail (m
->priv
->is_server
&& !m
->priv
->is_client
);
990 g_return_if_fail (m
->priv
->state
== G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA
);
995 tokens
= g_strsplit (data
, " ", 0);
996 if (g_strv_length (tokens
) != 2)
998 g_warning ("Malformed data `%s'", data
);
999 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
1003 client_challenge
= tokens
[0];
1004 alleged_sha1
= tokens
[1];
1006 sha1
= generate_sha1 (m
->priv
->server_challenge
, client_challenge
, m
->priv
->cookie
);
1008 if (g_strcmp0 (sha1
, alleged_sha1
) == 0)
1010 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED
;
1014 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
1018 g_strfreev (tokens
);
1023 mechanism_server_data_send (GDBusAuthMechanism
*mechanism
,
1024 gsize
*out_data_len
)
1026 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1029 const gchar
*cookie_context
;
1032 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), NULL
);
1033 g_return_val_if_fail (m
->priv
->is_server
&& !m
->priv
->is_client
, NULL
);
1034 g_return_val_if_fail (m
->priv
->state
== G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND
, NULL
);
1038 /* TODO: use GDBusAuthObserver here to get the cookie context to use? */
1039 cookie_context
= "org_gtk_gdbus_general";
1043 if (!keyring_generate_entry (cookie_context
,
1048 g_warning ("Error adding entry to keyring: %s", error
->message
);
1049 g_error_free (error
);
1050 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
1054 m
->priv
->server_challenge
= random_ascii_string (16);
1055 s
= g_strdup_printf ("%s %d %s",
1058 m
->priv
->server_challenge
);
1060 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA
;
1067 mechanism_server_get_reject_reason (GDBusAuthMechanism
*mechanism
)
1069 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1071 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), NULL
);
1072 g_return_val_if_fail (m
->priv
->is_server
&& !m
->priv
->is_client
, NULL
);
1073 g_return_val_if_fail (m
->priv
->state
== G_DBUS_AUTH_MECHANISM_STATE_REJECTED
, NULL
);
1075 /* can never end up here because we are never in the REJECTED state */
1076 g_assert_not_reached ();
1082 mechanism_server_shutdown (GDBusAuthMechanism
*mechanism
)
1084 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1086 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
));
1087 g_return_if_fail (m
->priv
->is_server
&& !m
->priv
->is_client
);
1089 m
->priv
->is_server
= FALSE
;
1092 /* ---------------------------------------------------------------------------------------------------- */
1094 static GDBusAuthMechanismState
1095 mechanism_client_get_state (GDBusAuthMechanism
*mechanism
)
1097 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1099 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), G_DBUS_AUTH_MECHANISM_STATE_INVALID
);
1100 g_return_val_if_fail (m
->priv
->is_client
&& !m
->priv
->is_server
, G_DBUS_AUTH_MECHANISM_STATE_INVALID
);
1102 return m
->priv
->state
;
1106 mechanism_client_initiate (GDBusAuthMechanism
*mechanism
,
1107 gsize
*out_initial_response_len
)
1109 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1110 gchar
*initial_response
;
1112 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), NULL
);
1113 g_return_val_if_fail (!m
->priv
->is_server
&& !m
->priv
->is_client
, NULL
);
1115 m
->priv
->is_client
= TRUE
;
1116 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA
;
1118 *out_initial_response_len
= -1;
1121 initial_response
= g_strdup_printf ("%" G_GINT64_FORMAT
, (gint64
) getuid ());
1122 #elif defined (G_OS_WIN32)
1123 initial_response
= _g_dbus_win32_get_user_sid ();
1125 #error Please implement for your OS
1127 g_assert (initial_response
!= NULL
);
1129 return initial_response
;
1133 mechanism_client_data_receive (GDBusAuthMechanism
*mechanism
,
1137 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1139 const gchar
*cookie_context
;
1141 const gchar
*server_challenge
;
1142 gchar
*client_challenge
;
1148 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
));
1149 g_return_if_fail (m
->priv
->is_client
&& !m
->priv
->is_server
);
1150 g_return_if_fail (m
->priv
->state
== G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA
);
1154 client_challenge
= NULL
;
1156 tokens
= g_strsplit (data
, " ", 0);
1157 if (g_strv_length (tokens
) != 3)
1159 g_warning ("Malformed data `%s'", data
);
1160 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
1164 cookie_context
= tokens
[0];
1165 cookie_id
= g_ascii_strtoll (tokens
[1], &endp
, 10);
1168 g_warning ("Malformed cookie_id `%s'", tokens
[1]);
1169 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
1172 server_challenge
= tokens
[2];
1175 cookie
= keyring_lookup_entry (cookie_context
, cookie_id
, &error
);
1178 g_warning ("Problems looking up entry in keyring: %s", error
->message
);
1179 g_error_free (error
);
1180 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_REJECTED
;
1184 client_challenge
= random_ascii_string (16);
1185 sha1
= generate_sha1 (server_challenge
, client_challenge
, cookie
);
1186 m
->priv
->to_send
= g_strdup_printf ("%s %s", client_challenge
, sha1
);
1188 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND
;
1191 g_strfreev (tokens
);
1193 g_free (client_challenge
);
1197 mechanism_client_data_send (GDBusAuthMechanism
*mechanism
,
1198 gsize
*out_data_len
)
1200 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1202 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
), NULL
);
1203 g_return_val_if_fail (m
->priv
->is_client
&& !m
->priv
->is_server
, NULL
);
1204 g_return_val_if_fail (m
->priv
->state
== G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND
, NULL
);
1206 g_assert (m
->priv
->to_send
!= NULL
);
1208 m
->priv
->state
= G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED
;
1210 return g_strdup (m
->priv
->to_send
);
1214 mechanism_client_shutdown (GDBusAuthMechanism
*mechanism
)
1216 GDBusAuthMechanismSha1
*m
= G_DBUS_AUTH_MECHANISM_SHA1 (mechanism
);
1218 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism
));
1219 g_return_if_fail (m
->priv
->is_client
&& !m
->priv
->is_server
);
1221 m
->priv
->is_client
= FALSE
;
1224 /* ---------------------------------------------------------------------------------------------------- */