diff options
author | David Zeuthen <davidz@redhat.com> | 2010-05-05 16:37:34 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2010-05-05 16:37:34 -0400 |
commit | 2e8b6fa0282e229d743aa2ceefbfe789e5e1b0b9 (patch) | |
tree | 21177446586258699a1bd58906d90e2d6d89eab9 | |
parent | 7e2610fb01367ce66af6cd0b5ae48be0413ec0a5 (diff) |
Actually check user in the EXTERNAL authentication mechanism
-rw-r--r-- | gdbus/gdbusauthmechanismexternal.c | 153 |
1 files changed, 81 insertions, 72 deletions
diff --git a/gdbus/gdbusauthmechanismexternal.c b/gdbus/gdbusauthmechanismexternal.c index aceeade..8884ed5 100644 --- a/gdbus/gdbusauthmechanismexternal.c +++ b/gdbus/gdbusauthmechanismexternal.c @@ -25,6 +25,7 @@ #include <glib/gi18n.h> #include "gdbusauthmechanismexternal.h" +#include "gcredentials.h" #include "gdbuserror.h" #include "gdbusenumtypes.h" @@ -184,6 +185,56 @@ mechanism_server_get_state (GDBusAuthMechanism *mechanism) return m->priv->state; } +static gboolean +data_matches_credentials (const gchar *data, + GCredentials *credentials) +{ + gboolean match; + + match = FALSE; + + if (credentials == NULL) + goto out; + + if (data == NULL || strlen (data) == 0) + goto out; + +#if defined(G_OS_UNIX) + { + gint64 alleged_uid; + gchar *endp; + + /* on UNIX, this is the uid as a string in base 10 */ + alleged_uid = g_ascii_strtoll (data, &endp, 10); + if (*endp == '\0') + { + if (g_credentials_has_unix_user (credentials) && + g_credentials_get_unix_user (credentials) == alleged_uid) + { + match = TRUE; + } + } + } +#elif defined(G_OS_WIN32) + { + const gchar *alleged_sid; + + /* on Win32, this is the User SID */ + alleged_sid = data; + if (g_credentials_has_windows_user (credentials) && + g_strcmp0 (g_credentials_get_windows_user (credentials), alleged_sid) == 0) + { + match = TRUE; + } + } +#else +#warning Dont know how to read credentials on this OS. Please implement. +#endif + + out: + return match; +} + static void mechanism_server_initiate (GDBusAuthMechanism *mechanism, const gchar *initial_response, @@ -194,17 +245,23 @@ mechanism_server_initiate (GDBusAuthMechanism *mechanism, g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism)); g_return_if_fail (!m->priv->is_server && !m->priv->is_client); + m->priv->is_server = TRUE; + if (initial_response != NULL) { - g_debug ("EXTERNAL: initial_response was `%s'", initial_response); - g_debug ("EXTERNAL: credentials `%p'", _g_dbus_auth_mechanism_get_credentials (G_DBUS_AUTH_MECHANISM (mechanism))); + if (data_matches_credentials (initial_response, _g_dbus_auth_mechanism_get_credentials (mechanism))) + { + m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED; + } + else + { + m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED; + } + } + else + { + m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA; } - - m->priv->is_server = TRUE; - - /* TODO: actually check that the credentials match */ - m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED; - //m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED; } static void @@ -218,8 +275,14 @@ mechanism_server_data_receive (GDBusAuthMechanism *mechanism, g_return_if_fail (m->priv->is_server && !m->priv->is_client); g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA); - /* can never end up here because we are never in the WAITING_FOR_DATA state */ - g_assert_not_reached (); + if (data_matches_credentials (data, _g_dbus_auth_mechanism_get_credentials (mechanism))) + { + m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED; + } + else + { + m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED; + } } static gchar * @@ -277,70 +340,13 @@ mechanism_client_get_state (GDBusAuthMechanism *mechanism) return m->priv->state; } -#ifdef G_OS_WIN32 -#include <windows.h> - -/* Declarations missing in mingw's headers */ -extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid); -extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid); - -static gchar * -_get_win32_sid (void) -{ - HANDLE process_token = INVALID_HANDLE_VALUE; - TOKEN_USER *token_user = NULL; - DWORD n; - PSID psid; - int retval = FALSE; - gchar *sid; - gchar *ret; - - ret = NULL; - - if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token)) - { - g_warning ("OpenProcessToken failed", GetLastError ()); - goto failed; - } - - if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n) && GetLastError () != ERROR_INSUFFICIENT_BUFFER) || - ((token_user = alloca (n)) == NULL) || - !GetTokenInformation (process_token, TokenUser, token_user, n, &n)) - { - g_warning ("GetTokenInformation failed", GetLastError ()); - goto failed; - } - - psid = token_user->User.Sid; - if (!IsValidSid (psid)) - { - g_warning ("Invalid SID"); - goto failed; - } - - if (!ConvertSidToStringSidA (psid, &sid)) - { - g_warning ("Invalid SID"); - goto failed; - } - - ret = g_strdup (sid); - LocalFree (sid); - -failed: - if (process_token != INVALID_HANDLE_VALUE) - CloseHandle (process_token); - - return ret; -} -#endif - static gchar * mechanism_client_initiate (GDBusAuthMechanism *mechanism, gsize *out_initial_response_len) { GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism); gchar *initial_response; + GCredentials *credentials; g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL); g_return_val_if_fail (!m->priv->is_server && !m->priv->is_client, NULL); @@ -350,14 +356,17 @@ mechanism_client_initiate (GDBusAuthMechanism *mechanism, *out_initial_response_len = -1; + credentials = _g_dbus_auth_mechanism_get_credentials (mechanism); + g_assert (credentials != NULL); + /* return the uid */ #if defined(G_OS_UNIX) - initial_response = g_strdup_printf ("%d", geteuid ()); + initial_response = g_strdup_printf ("%" G_GINT64_FORMAT, g_credentials_get_unix_user (credentials)); #elif defined(G_OS_WIN32) - initial_response = _get_win32_sid (); + initial_response = g_strdup_printf ("%s", g_credentials_get_windows_user ()); #else - initial_response = NULL; -#error TODO +#warning Dont know how to send credentials on this OS. Please implement. + m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED; #endif return initial_response; } |