/* * Syncdaemon API * * Authors: Rodrigo Moya * * Copyright 2010 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * */ #include #include #include #include "syncdaemon-authentication.h" #include "syncdaemon-marshal.h" G_DEFINE_TYPE(SyncdaemonAuthentication, syncdaemon_authentication, G_TYPE_OBJECT) struct _SyncdaemonAuthenticationPrivate { DBusGConnection *bus; DBusGProxy *proxy; gboolean has_credentials; SyncdaemonCredentials *credentials; }; /* Signals */ enum { CREDENTIALS_FOUND_SIGNAL, AUTHORIZATION_CANCELLED_SIGNAL, ERROR_SIGNAL, LAST_SIGNAL }; static guint auth_signals[LAST_SIGNAL] = { 0, }; static void syncdaemon_authentication_finalize (GObject *object) { SyncdaemonAuthentication *auth = SYNCDAEMON_AUTHENTICATION (object); if (auth->priv != NULL) { if (auth->priv->credentials != NULL) g_object_unref (G_OBJECT (auth->priv->credentials)); if (auth->priv->proxy != NULL) g_object_unref (G_OBJECT (auth->priv->proxy)); if (auth->priv->bus != NULL) dbus_g_connection_unref (auth->priv->bus); g_free (auth->priv); } G_OBJECT_CLASS (syncdaemon_authentication_parent_class)->finalize (object); } static void syncdaemon_authentication_class_init (SyncdaemonAuthenticationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = syncdaemon_authentication_finalize; /* Register signals */ auth_signals[CREDENTIALS_FOUND_SIGNAL] = g_signal_new ("credentials_found", G_TYPE_FROM_CLASS (klass), (GSignalFlags) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (SyncdaemonAuthenticationClass, credentials_found), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); auth_signals[AUTHORIZATION_CANCELLED_SIGNAL] = g_signal_new ("authorization_cancelled", G_TYPE_FROM_CLASS (klass), (GSignalFlags) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (SyncdaemonAuthenticationClass, authorization_cancelled), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); auth_signals[ERROR_SIGNAL] = g_signal_new ("error", G_TYPE_FROM_CLASS (klass), (GSignalFlags) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (SyncdaemonAuthenticationClass, error), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); } static void credentials_found_cb (DBusGProxy *proxy, const gchar *app_name, GHashTable *result, gpointer user_data) { SyncdaemonAuthentication *auth = SYNCDAEMON_AUTHENTICATION (user_data); if (g_strcmp0 (app_name, SSO_APP_NAME) != 0) { g_debug ("Credentials are not for '" SSO_APP_NAME "', ignoring"); return; } if (auth->priv->credentials != NULL) g_object_unref (G_OBJECT (auth->priv->credentials)); auth->priv->credentials = syncdaemon_credentials_new_from_hash_table (result); auth->priv->has_credentials = TRUE; g_signal_emit (auth, auth_signals[CREDENTIALS_FOUND_SIGNAL], 0, auth->priv->credentials); } static void authorization_denied_cb (DBusGProxy *proxy, const gchar *app_name, gpointer user_data) { g_debug ("Authorization denied"); if (g_strcmp0 (app_name, SSO_APP_NAME) != 0) { g_debug ("Credentials are not for '" SSO_APP_NAME "', ignoring"); return; } g_signal_emit (user_data, auth_signals[AUTHORIZATION_CANCELLED_SIGNAL], 0); } static void credentials_error_cb (DBusGProxy *proxy, const gchar *app_name, const gchar *error_message, const gchar *detailed_error, gpointer user_data) { g_debug ("Authorization error"); if (g_strcmp0 (app_name, SSO_APP_NAME) != 0) { g_debug ("Credentials are not for '" SSO_APP_NAME "', ignoring"); return; } g_signal_emit (user_data, auth_signals[ERROR_SIGNAL], 0, error_message); } static void syncdaemon_authentication_init (SyncdaemonAuthentication *auth) { GError *error = NULL; auth->priv = g_new0 (SyncdaemonAuthenticationPrivate, 1); auth->priv->has_credentials = FALSE; /* Initialize DBus */ auth->priv->bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); if (error != NULL) { g_warning ("Couldn't get session bus: %s", error->message); g_error_free (error); } else { auth->priv->proxy = dbus_g_proxy_new_for_name (auth->priv->bus, "com.ubuntu.sso", "/credentials", "com.ubuntu.sso.ApplicationCredentials"); if (auth->priv->proxy != NULL) { dbus_g_object_register_marshaller (_syncdaemon_marshal_VOID__STRING_POINTER, G_TYPE_NONE, G_TYPE_STRING, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_INVALID); dbus_g_proxy_add_signal (auth->priv->proxy, "CredentialsFound", G_TYPE_STRING, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_INVALID); dbus_g_proxy_connect_signal (auth->priv->proxy, "CredentialsFound", G_CALLBACK (credentials_found_cb), auth, NULL); dbus_g_proxy_add_signal (auth->priv->proxy, "AuthorizationDenied", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (auth->priv->proxy, "AuthorizationDenied", G_CALLBACK (authorization_denied_cb), auth, NULL); dbus_g_proxy_add_signal (auth->priv->proxy, "CredentialsError", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (auth->priv->proxy, "CredentialsError", G_CALLBACK (credentials_error_cb), auth, NULL); } else g_warning ("Couldn't get proxy for com.ubuntu.sso"); } } /** * syncdaemon_authentication_find_credentials: */ SyncdaemonCredentials * syncdaemon_authentication_find_credentials (SyncdaemonAuthentication *auth) { g_return_val_if_fail (SYNCDAEMON_IS_AUTHENTICATION (auth), NULL); if (!auth->priv->has_credentials) { GHashTable *credentials; GError *error = NULL; if (dbus_g_proxy_call (auth->priv->proxy, "find_credentials", &error, G_TYPE_STRING, SSO_APP_NAME, G_TYPE_INVALID, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), &credentials, G_TYPE_INVALID)) { if (g_hash_table_size (credentials) >= 4) { auth->priv->credentials = syncdaemon_credentials_new_from_hash_table (credentials); auth->priv->has_credentials = TRUE; } else g_warning ("Got less number of items in credentials hash table than expected!"); g_hash_table_destroy (credentials); } else { g_warning ("Could not get credentials for '" SSO_APP_NAME "': %s", error->message); g_error_free (error); return NULL; } } return auth->priv->credentials; } /** * syncdaemon_authentication_has_credentials: */ gboolean syncdaemon_authentication_has_credentials (SyncdaemonAuthentication *auth) { g_return_val_if_fail (SYNCDAEMON_IS_AUTHENTICATION (auth), FALSE); if (auth->priv->has_credentials) return TRUE; return syncdaemon_authentication_find_credentials (auth) != NULL; } /** * syncdaemon_authentication_login_or_register: */ void syncdaemon_authentication_login_or_register (SyncdaemonAuthentication *auth) { GError *error = NULL; g_return_if_fail (SYNCDAEMON_IS_AUTHENTICATION (auth)); if (!dbus_g_proxy_call (auth->priv->proxy, "login_or_register_to_get_credentials", &error, G_TYPE_STRING, SSO_APP_NAME, G_TYPE_STRING, SSO_TC_URL, G_TYPE_STRING, _(SSO_DESCRIPTION), G_TYPE_INT64, 0, /* FIXME */ G_TYPE_INVALID, G_TYPE_INVALID)) { g_warning ("Could not login or register for 'ubuntuone': %s", error->message); g_error_free (error); } }