* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "config.h"
#include "empathy-auth-factory.h"
-#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
+#include <tp-account-widgets/tpaw-keyring.h>
-#define DEBUG_FLAG EMPATHY_DEBUG_TLS
-#include "empathy-debug.h"
-#include "empathy-keyring.h"
+#include "empathy-sasl-mechanisms.h"
#include "empathy-server-sasl-handler.h"
#include "empathy-server-tls-handler.h"
-#include "empathy-goa-auth-handler.h"
#include "empathy-utils.h"
-#include "extensions/extensions.h"
+#ifdef HAVE_GOA
+#include "empathy-goa-auth-handler.h"
+#endif /* HAVE_GOA */
+
+#ifdef HAVE_UOA
+#include "empathy-uoa-auth-handler.h"
+#endif /* HAVE_UOA */
+
+#define DEBUG_FLAG EMPATHY_DEBUG_TLS
+#include "empathy-debug.h"
G_DEFINE_TYPE (EmpathyAuthFactory, empathy_auth_factory, TP_TYPE_BASE_CLIENT);
* reffed (EmpathyServerSASLHandler *)
* */
GHashTable *sasl_handlers;
+
+#ifdef HAVE_GOA
EmpathyGoaAuthHandler *goa_handler;
+#endif /* HAVE_GOA */
+
+#ifdef HAVE_UOA
+ EmpathyUoaAuthHandler *uoa_handler;
+#endif /* HAVE_UOA */
+
+ /* If an account failed to connect and user enters a new password to try, we
+ * store it in this hash table and will try to use it next time the account
+ * attemps to connect.
+ *
+ * reffed TpAccount -> owned password (gchar *) */
+ GHashTable *retry_passwords;
gboolean dispose_run;
};
enum {
NEW_SERVER_TLS_HANDLER,
NEW_SERVER_SASL_HANDLER,
+ AUTH_PASSWORD_FAILED,
LAST_SIGNAL,
};
g_hash_table_remove (priv->sasl_handlers, tp_proxy_get_object_path (channel));
}
+static void
+sasl_handler_auth_password_failed_cb (EmpathyServerSASLHandler *handler,
+ const gchar *password,
+ EmpathyAuthFactory *self)
+{
+ TpAccount *account;
+
+ account = empathy_server_sasl_handler_get_account (handler);
+
+ g_signal_emit (self, signals[AUTH_PASSWORD_FAILED], 0, account, password);
+}
+
static void
server_sasl_handler_ready_cb (GObject *source,
GAsyncResult *res,
else
{
TpChannel *channel;
+ const gchar *password;
+ TpAccount *account;
if (data->context != NULL)
tp_handle_channels_context_accept (data->context);
tp_g_signal_connect_object (handler, "invalidated",
G_CALLBACK (sasl_handler_invalidated_cb), data->self, 0);
+ tp_g_signal_connect_object (handler, "auth-password-failed",
+ G_CALLBACK (sasl_handler_auth_password_failed_cb), data->self, 0);
+
+ /* Is there a retry password? */
+ account = empathy_server_sasl_handler_get_account (handler);
+
+ password = g_hash_table_lookup (data->self->priv->retry_passwords,
+ account);
+ if (password != NULL)
+ {
+ gboolean save;
+
+ DEBUG ("Use retry password");
+
+ /* We want to save this new password only if there is another
+ * (wrong) password saved. The SASL handler will only save it if it
+ * manages to connect. */
+ save = empathy_server_sasl_handler_has_password (handler);
+
+ empathy_server_sasl_handler_provide_password (handler,
+ password, save);
+
+ /* We only want to try this password once */
+ g_hash_table_remove (data->self->priv->retry_passwords, account);
+ }
+
g_signal_emit (data->self, signals[NEW_SERVER_SASL_HANDLER], 0,
handler);
}
* ServerTLSConnection channels. */
if (observe
|| tp_channel_get_channel_type_id (channel) !=
- EMP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION)
+ TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION)
{
g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"Can only %s ServerTLSConnection or ServerAuthentication channels, "
/* create a handler */
if (tp_channel_get_channel_type_id (channel) ==
- EMP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION)
+ TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION)
{
empathy_server_tls_handler_new_async (channel, server_tls_handler_ready_cb,
data);
{
ObserveChannelsData *data = user_data;
- if (empathy_keyring_get_account_password_finish (TP_ACCOUNT (source), result, NULL) == NULL)
+ if (tpaw_keyring_get_account_password_finish (TP_ACCOUNT (source), result, NULL) == NULL)
{
/* We don't actually mind if this fails, just let the approver
* go ahead and take the channel. */
}
}
+#ifdef HAVE_GOA
static void
goa_claim_cb (GObject *source,
GAsyncResult *result,
observe_channels_data_free (data);
}
+#endif /* HAVE_GOA */
+
+#ifdef HAVE_UOA
+static void
+uoa_claim_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ObserveChannelsData *data = user_data;
+ EmpathyAuthFactory *self = data->self;
+ GError *error = NULL;
+
+ if (!tp_channel_dispatch_operation_claim_with_finish (data->dispatch_operation,
+ result, &error))
+ {
+ DEBUG ("Failed to claim: %s", error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ empathy_uoa_auth_handler_start (self->priv->uoa_handler,
+ data->channel, data->account);
+ }
+
+ observe_channels_data_free (data);
+}
+#endif /* HAVE_UOA */
static void
observe_channels (TpBaseClient *client,
data->account = g_object_ref (account);
data->channel = g_object_ref (channel);
+#ifdef HAVE_GOA
/* GOA auth? */
if (empathy_goa_auth_handler_supports (self->priv->goa_handler, channel, account))
{
tp_observe_channels_context_accept (context);
return;
}
+#endif /* HAVE_GOA */
+
+#ifdef HAVE_UOA
+ /* UOA auth? */
+ if (empathy_uoa_auth_handler_supports (self->priv->uoa_handler, channel, account))
+ {
+ DEBUG ("Supported UOA account (%s), claim SASL channel",
+ tp_proxy_get_object_path (account));
+
+ tp_channel_dispatch_operation_claim_with_async (dispatch_operation,
+ client, uoa_claim_cb, data);
+ tp_observe_channels_context_accept (context);
+ return;
+ }
+#endif /* HAVE_UOA */
/* Password auth? */
if (empathy_sasl_channel_supports_mechanism (data->channel,
"X-TELEPATHY-PASSWORD"))
{
- empathy_keyring_get_account_password_async (data->account,
+ if (g_hash_table_lookup (self->priv->retry_passwords, account) != NULL)
+ {
+ DEBUG ("We have a retry password for account %s, calling Claim",
+ tp_account_get_path_suffix (account));
+
+ tp_channel_dispatch_operation_claim_with_async (dispatch_operation,
+ client, password_claim_cb, data);
+
+ tp_observe_channels_context_accept (context);
+ return;
+ }
+
+ tpaw_keyring_get_account_password_async (data->account,
get_password_cb, data);
tp_observe_channels_context_delay (context);
return;
self->priv->sasl_handlers = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, g_object_unref);
+
+#ifdef HAVE_GOA
self->priv->goa_handler = empathy_goa_auth_handler_new ();
+#endif /* HAVE_GOA */
+
+#ifdef HAVE_UOA
+ self->priv->uoa_handler = empathy_uoa_auth_handler_new ();
+#endif /* HAVE_UOA */
+
+ self->priv->retry_passwords = g_hash_table_new_full (NULL, NULL,
+ g_object_unref, g_free);
}
static void
tp_base_client_take_handler_filter (client, tp_asv_new (
/* ChannelType */
TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
- EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
+ TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
/* AuthenticationMethod */
TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
TP_HANDLE_TYPE_NONE, NULL));
priv->dispose_run = TRUE;
g_hash_table_unref (priv->sasl_handlers);
+
+#ifdef HAVE_GOA
g_object_unref (priv->goa_handler);
+#endif /* HAVE_GOA */
+
+#ifdef HAVE_UOA
+ g_object_unref (priv->uoa_handler);
+#endif /* HAVE_UOA */
+
+ g_hash_table_unref (priv->retry_passwords);
G_OBJECT_CLASS (empathy_auth_factory_parent_class)->dispose (object);
}
g_cclosure_marshal_generic,
G_TYPE_NONE,
1, EMPATHY_TYPE_SERVER_SASL_HANDLER);
+
+ signals[AUTH_PASSWORD_FAILED] =
+ g_signal_new ("auth-password-failed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, 0,
+ NULL, NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 2, TP_TYPE_ACCOUNT, G_TYPE_STRING);
}
EmpathyAuthFactory *
{
return tp_base_client_register (TP_BASE_CLIENT (self), error);
}
+
+void
+empathy_auth_factory_save_retry_password (EmpathyAuthFactory *self,
+ TpAccount *account,
+ const gchar *password)
+{
+ g_hash_table_insert (self->priv->retry_passwords,
+ g_object_ref (account), g_strdup (password));
+}