Update Slovak translation
[empathy-mirror.git] / libempathy / empathy-auth-factory.c
blob04e619bd03cf20942c6c1f98c2a5edaa5c2c2acb
1 /*
2 * empathy-auth-factory.c - Source for EmpathyAuthFactory
3 * Copyright (C) 2010 Collabora Ltd.
4 * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "config.h"
22 #include "empathy-auth-factory.h"
24 #include <telepathy-glib/telepathy-glib-dbus.h>
25 #include <tp-account-widgets/tpaw-keyring.h>
27 #include "empathy-sasl-mechanisms.h"
28 #include "empathy-server-sasl-handler.h"
29 #include "empathy-server-tls-handler.h"
30 #include "empathy-utils.h"
32 #ifdef HAVE_GOA
33 #include "empathy-goa-auth-handler.h"
34 #endif /* HAVE_GOA */
36 #ifdef HAVE_UOA
37 #include "empathy-uoa-auth-handler.h"
38 #endif /* HAVE_UOA */
40 #define DEBUG_FLAG EMPATHY_DEBUG_TLS
41 #include "empathy-debug.h"
43 G_DEFINE_TYPE (EmpathyAuthFactory, empathy_auth_factory, TP_TYPE_BASE_CLIENT);
45 struct _EmpathyAuthFactoryPriv {
46 /* Keep a ref here so the auth client doesn't have to mess with
47 * refs. It will be cleared when the channel (and so the handler)
48 * gets invalidated.
50 * The channel path of the handler's channel (borrowed gchar *) ->
51 * reffed (EmpathyServerSASLHandler *)
52 * */
53 GHashTable *sasl_handlers;
55 #ifdef HAVE_GOA
56 EmpathyGoaAuthHandler *goa_handler;
57 #endif /* HAVE_GOA */
59 #ifdef HAVE_UOA
60 EmpathyUoaAuthHandler *uoa_handler;
61 #endif /* HAVE_UOA */
63 /* If an account failed to connect and user enters a new password to try, we
64 * store it in this hash table and will try to use it next time the account
65 * attemps to connect.
67 * reffed TpAccount -> owned password (gchar *) */
68 GHashTable *retry_passwords;
70 gboolean dispose_run;
73 enum {
74 NEW_SERVER_TLS_HANDLER,
75 NEW_SERVER_SASL_HANDLER,
76 AUTH_PASSWORD_FAILED,
77 LAST_SIGNAL,
80 static guint signals[LAST_SIGNAL] = { 0, };
82 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAuthFactory)
84 static EmpathyAuthFactory *auth_factory_singleton = NULL;
86 typedef struct {
87 TpHandleChannelsContext *context;
88 EmpathyAuthFactory *self;
89 } HandlerContextData;
91 static void
92 handler_context_data_free (HandlerContextData *data)
94 tp_clear_object (&data->self);
95 tp_clear_object (&data->context);
97 g_slice_free (HandlerContextData, data);
100 static HandlerContextData *
101 handler_context_data_new (EmpathyAuthFactory *self,
102 TpHandleChannelsContext *context)
104 HandlerContextData *data;
106 data = g_slice_new0 (HandlerContextData);
107 data->self = g_object_ref (self);
109 if (context != NULL)
110 data->context = g_object_ref (context);
112 return data;
115 static void
116 server_tls_handler_ready_cb (GObject *source,
117 GAsyncResult *res,
118 gpointer user_data)
120 EmpathyServerTLSHandler *handler;
121 GError *error = NULL;
122 HandlerContextData *data = user_data;
124 handler = empathy_server_tls_handler_new_finish (res, &error);
126 if (error != NULL)
128 DEBUG ("Failed to create a server TLS handler; error %s",
129 error->message);
130 tp_handle_channels_context_fail (data->context, error);
132 g_error_free (error);
134 else
136 tp_handle_channels_context_accept (data->context);
137 g_signal_emit (data->self, signals[NEW_SERVER_TLS_HANDLER], 0,
138 handler);
140 g_object_unref (handler);
143 handler_context_data_free (data);
146 static void
147 sasl_handler_invalidated_cb (EmpathyServerSASLHandler *handler,
148 gpointer user_data)
150 EmpathyAuthFactory *self = user_data;
151 EmpathyAuthFactoryPriv *priv = GET_PRIV (self);
152 TpChannel * channel;
154 channel = empathy_server_sasl_handler_get_channel (handler);
155 g_assert (channel != NULL);
157 DEBUG ("SASL handler for channel %s is invalidated, unref it",
158 tp_proxy_get_object_path (channel));
160 g_hash_table_remove (priv->sasl_handlers, tp_proxy_get_object_path (channel));
163 static void
164 sasl_handler_auth_password_failed_cb (EmpathyServerSASLHandler *handler,
165 const gchar *password,
166 EmpathyAuthFactory *self)
168 TpAccount *account;
170 account = empathy_server_sasl_handler_get_account (handler);
172 g_signal_emit (self, signals[AUTH_PASSWORD_FAILED], 0, account, password);
175 static void
176 server_sasl_handler_ready_cb (GObject *source,
177 GAsyncResult *res,
178 gpointer user_data)
180 EmpathyAuthFactoryPriv *priv;
181 GError *error = NULL;
182 HandlerContextData *data = user_data;
183 EmpathyServerSASLHandler *handler;
185 priv = GET_PRIV (data->self);
186 handler = empathy_server_sasl_handler_new_finish (res, &error);
188 if (error != NULL)
190 DEBUG ("Failed to create a server SASL handler; error %s",
191 error->message);
193 if (data->context != NULL)
194 tp_handle_channels_context_fail (data->context, error);
196 g_error_free (error);
198 else
200 TpChannel *channel;
201 const gchar *password;
202 TpAccount *account;
204 if (data->context != NULL)
205 tp_handle_channels_context_accept (data->context);
207 channel = empathy_server_sasl_handler_get_channel (handler);
208 g_assert (channel != NULL);
210 /* Pass the ref to the hash table */
211 g_hash_table_insert (priv->sasl_handlers,
212 (gpointer) tp_proxy_get_object_path (channel), handler);
214 tp_g_signal_connect_object (handler, "invalidated",
215 G_CALLBACK (sasl_handler_invalidated_cb), data->self, 0);
217 tp_g_signal_connect_object (handler, "auth-password-failed",
218 G_CALLBACK (sasl_handler_auth_password_failed_cb), data->self, 0);
220 /* Is there a retry password? */
221 account = empathy_server_sasl_handler_get_account (handler);
223 password = g_hash_table_lookup (data->self->priv->retry_passwords,
224 account);
225 if (password != NULL)
227 gboolean save;
229 DEBUG ("Use retry password");
231 /* We want to save this new password only if there is another
232 * (wrong) password saved. The SASL handler will only save it if it
233 * manages to connect. */
234 save = empathy_server_sasl_handler_has_password (handler);
236 empathy_server_sasl_handler_provide_password (handler,
237 password, save);
239 /* We only want to try this password once */
240 g_hash_table_remove (data->self->priv->retry_passwords, account);
243 g_signal_emit (data->self, signals[NEW_SERVER_SASL_HANDLER], 0,
244 handler);
247 handler_context_data_free (data);
250 static gboolean
251 common_checks (EmpathyAuthFactory *self,
252 GList *channels,
253 gboolean observe,
254 GError **error)
256 EmpathyAuthFactoryPriv *priv = GET_PRIV (self);
257 TpChannel *channel;
258 const GError *dbus_error;
259 EmpathyServerSASLHandler *handler;
261 /* there can't be more than one ServerTLSConnection or
262 * ServerAuthentication channels at the same time, for the same
263 * connection/account.
265 if (g_list_length (channels) != 1)
267 g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
268 "Can't %s more than one ServerTLSConnection or ServerAuthentication "
269 "channel for the same connection.", observe ? "observe" : "handle");
271 return FALSE;
274 channel = channels->data;
276 if (tp_channel_get_channel_type_id (channel) !=
277 TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION)
279 /* If we are observing we care only about ServerAuthentication channels.
280 * If we are handling we care about ServerAuthentication and
281 * ServerTLSConnection channels. */
282 if (observe
283 || tp_channel_get_channel_type_id (channel) !=
284 TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION)
286 g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
287 "Can only %s ServerTLSConnection or ServerAuthentication channels, "
288 "this was a %s channel", observe ? "observe" : "handle",
289 tp_channel_get_channel_type (channel));
291 return FALSE;
295 handler = g_hash_table_lookup (priv->sasl_handlers,
296 tp_proxy_get_object_path (channel));
298 if (tp_channel_get_channel_type_id (channel) ==
299 TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION
300 && handler != NULL &&
301 !observe)
303 g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
304 "We are already handling this channel: %s",
305 tp_proxy_get_object_path (channel));
307 return FALSE;
310 dbus_error = tp_proxy_get_invalidated (channel);
311 if (dbus_error != NULL)
313 *error = g_error_copy (dbus_error);
314 return FALSE;
317 return TRUE;
320 static void
321 handle_channels (TpBaseClient *handler,
322 TpAccount *account,
323 TpConnection *connection,
324 GList *channels,
325 GList *requests_satisfied,
326 gint64 user_action_time,
327 TpHandleChannelsContext *context)
329 TpChannel *channel;
330 GError *error = NULL;
331 EmpathyAuthFactory *self = EMPATHY_AUTH_FACTORY (handler);
332 HandlerContextData *data;
334 DEBUG ("Handle TLS or SASL carrier channels.");
336 if (!common_checks (self, channels, FALSE, &error))
338 DEBUG ("Failed checks: %s", error->message);
339 tp_handle_channels_context_fail (context, error);
340 g_clear_error (&error);
341 return;
344 /* The common checks above have checked this is fine. */
345 channel = channels->data;
347 /* Only password authentication is supported from here */
348 if (tp_channel_get_channel_type_id (channel) ==
349 TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION &&
350 !empathy_sasl_channel_supports_mechanism (channel,
351 "X-TELEPATHY-PASSWORD"))
353 g_set_error_literal (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
354 "Only the X-TELEPATHY-PASSWORD SASL mechanism is supported");
355 DEBUG ("%s", error->message);
356 tp_handle_channels_context_fail (context, error);
357 g_clear_error (&error);
358 return;
361 data = handler_context_data_new (self, context);
362 tp_handle_channels_context_delay (context);
364 /* create a handler */
365 if (tp_channel_get_channel_type_id (channel) ==
366 TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION)
368 empathy_server_tls_handler_new_async (channel, server_tls_handler_ready_cb,
369 data);
371 else if (tp_channel_get_channel_type_id (channel) ==
372 TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION)
374 empathy_server_sasl_handler_new_async (account, channel,
375 server_sasl_handler_ready_cb, data);
379 typedef struct
381 EmpathyAuthFactory *self;
382 TpObserveChannelsContext *context;
383 TpChannelDispatchOperation *dispatch_operation;
384 TpAccount *account;
385 TpChannel *channel;
386 } ObserveChannelsData;
388 static void
389 observe_channels_data_free (ObserveChannelsData *data)
391 g_object_unref (data->context);
392 g_object_unref (data->account);
393 g_object_unref (data->channel);
394 g_object_unref (data->dispatch_operation);
395 g_slice_free (ObserveChannelsData, data);
398 static void
399 password_claim_cb (GObject *source,
400 GAsyncResult *result,
401 gpointer user_data)
403 ObserveChannelsData *data = user_data;
404 GError *error = NULL;
406 if (!tp_channel_dispatch_operation_claim_with_finish (
407 TP_CHANNEL_DISPATCH_OPERATION (source), result, &error))
409 DEBUG ("Failed to call Claim: %s", error->message);
410 g_clear_error (&error);
412 else
414 HandlerContextData *h_data;
416 DEBUG ("Claim called successfully");
418 h_data = handler_context_data_new (data->self, NULL);
420 empathy_server_sasl_handler_new_async (TP_ACCOUNT (data->account),
421 data->channel, server_sasl_handler_ready_cb, h_data);
424 observe_channels_data_free (data);
427 static void
428 get_password_cb (GObject *source,
429 GAsyncResult *result,
430 gpointer user_data)
432 ObserveChannelsData *data = user_data;
434 if (tpaw_keyring_get_account_password_finish (TP_ACCOUNT (source), result, NULL) == NULL)
436 /* We don't actually mind if this fails, just let the approver
437 * go ahead and take the channel. */
439 DEBUG ("We don't have a password for account %s, letting the event "
440 "manager approver take it", tp_proxy_get_object_path (source));
442 tp_observe_channels_context_accept (data->context);
443 observe_channels_data_free (data);
445 else
447 DEBUG ("We have a password for account %s, calling Claim",
448 tp_proxy_get_object_path (source));
450 tp_channel_dispatch_operation_claim_with_async (data->dispatch_operation,
451 TP_BASE_CLIENT (data->self), password_claim_cb, data);
453 tp_observe_channels_context_accept (data->context);
457 #ifdef HAVE_GOA
458 static void
459 goa_claim_cb (GObject *source,
460 GAsyncResult *result,
461 gpointer user_data)
463 ObserveChannelsData *data = user_data;
464 EmpathyAuthFactory *self = data->self;
465 GError *error = NULL;
467 if (!tp_channel_dispatch_operation_claim_with_finish (data->dispatch_operation,
468 result, &error))
470 DEBUG ("Failed to claim: %s", error->message);
471 g_clear_error (&error);
473 else
475 empathy_goa_auth_handler_start (self->priv->goa_handler,
476 data->channel, data->account);
479 observe_channels_data_free (data);
481 #endif /* HAVE_GOA */
483 #ifdef HAVE_UOA
484 static void
485 uoa_claim_cb (GObject *source,
486 GAsyncResult *result,
487 gpointer user_data)
489 ObserveChannelsData *data = user_data;
490 EmpathyAuthFactory *self = data->self;
491 GError *error = NULL;
493 if (!tp_channel_dispatch_operation_claim_with_finish (data->dispatch_operation,
494 result, &error))
496 DEBUG ("Failed to claim: %s", error->message);
497 g_clear_error (&error);
499 else
501 empathy_uoa_auth_handler_start (self->priv->uoa_handler,
502 data->channel, data->account);
505 observe_channels_data_free (data);
507 #endif /* HAVE_UOA */
509 static void
510 observe_channels (TpBaseClient *client,
511 TpAccount *account,
512 TpConnection *connection,
513 GList *channels,
514 TpChannelDispatchOperation *dispatch_operation,
515 GList *requests,
516 TpObserveChannelsContext *context)
518 EmpathyAuthFactory *self = EMPATHY_AUTH_FACTORY (client);
519 TpChannel *channel;
520 GError *error = NULL;
521 ObserveChannelsData *data;
523 DEBUG ("New auth channel to observe");
525 if (!common_checks (self, channels, TRUE, &error))
527 DEBUG ("Failed checks: %s", error->message);
528 tp_observe_channels_context_fail (context, error);
529 g_clear_error (&error);
530 return;
533 /* The common checks above have checked this is fine. */
534 channel = channels->data;
536 data = g_slice_new0 (ObserveChannelsData);
537 data->self = self;
538 data->context = g_object_ref (context);
539 data->dispatch_operation = g_object_ref (dispatch_operation);
540 data->account = g_object_ref (account);
541 data->channel = g_object_ref (channel);
543 #ifdef HAVE_GOA
544 /* GOA auth? */
545 if (empathy_goa_auth_handler_supports (self->priv->goa_handler, channel, account))
547 DEBUG ("Supported GOA account (%s), claim SASL channel",
548 tp_proxy_get_object_path (account));
550 tp_channel_dispatch_operation_claim_with_async (dispatch_operation,
551 client, goa_claim_cb, data);
552 tp_observe_channels_context_accept (context);
553 return;
555 #endif /* HAVE_GOA */
557 #ifdef HAVE_UOA
558 /* UOA auth? */
559 if (empathy_uoa_auth_handler_supports (self->priv->uoa_handler, channel, account))
561 DEBUG ("Supported UOA account (%s), claim SASL channel",
562 tp_proxy_get_object_path (account));
564 tp_channel_dispatch_operation_claim_with_async (dispatch_operation,
565 client, uoa_claim_cb, data);
566 tp_observe_channels_context_accept (context);
567 return;
569 #endif /* HAVE_UOA */
571 /* Password auth? */
572 if (empathy_sasl_channel_supports_mechanism (data->channel,
573 "X-TELEPATHY-PASSWORD"))
575 if (g_hash_table_lookup (self->priv->retry_passwords, account) != NULL)
577 DEBUG ("We have a retry password for account %s, calling Claim",
578 tp_account_get_path_suffix (account));
580 tp_channel_dispatch_operation_claim_with_async (dispatch_operation,
581 client, password_claim_cb, data);
583 tp_observe_channels_context_accept (context);
584 return;
587 tpaw_keyring_get_account_password_async (data->account,
588 get_password_cb, data);
589 tp_observe_channels_context_delay (context);
590 return;
593 /* Unknown auth */
594 error = g_error_new_literal (TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
595 "Unknown auth mechanism");
596 tp_observe_channels_context_fail (context, error);
597 g_clear_error (&error);
599 observe_channels_data_free (data);
602 static GObject *
603 empathy_auth_factory_constructor (GType type,
604 guint n_params,
605 GObjectConstructParam *params)
607 GObject *retval;
609 if (auth_factory_singleton != NULL)
611 retval = g_object_ref (auth_factory_singleton);
613 else
615 retval = G_OBJECT_CLASS (empathy_auth_factory_parent_class)->constructor
616 (type, n_params, params);
618 auth_factory_singleton = EMPATHY_AUTH_FACTORY (retval);
619 g_object_add_weak_pointer (retval, (gpointer *) &auth_factory_singleton);
622 return retval;
625 static void
626 empathy_auth_factory_init (EmpathyAuthFactory *self)
628 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
629 EMPATHY_TYPE_AUTH_FACTORY, EmpathyAuthFactoryPriv);
631 self->priv->sasl_handlers = g_hash_table_new_full (g_str_hash, g_str_equal,
632 NULL, g_object_unref);
634 #ifdef HAVE_GOA
635 self->priv->goa_handler = empathy_goa_auth_handler_new ();
636 #endif /* HAVE_GOA */
638 #ifdef HAVE_UOA
639 self->priv->uoa_handler = empathy_uoa_auth_handler_new ();
640 #endif /* HAVE_UOA */
642 self->priv->retry_passwords = g_hash_table_new_full (NULL, NULL,
643 g_object_unref, g_free);
646 static void
647 empathy_auth_factory_constructed (GObject *obj)
649 EmpathyAuthFactory *self = EMPATHY_AUTH_FACTORY (obj);
650 TpBaseClient *client = TP_BASE_CLIENT (self);
652 /* chain up to TpBaseClient first */
653 G_OBJECT_CLASS (empathy_auth_factory_parent_class)->constructed (obj);
655 tp_base_client_set_handler_bypass_approval (client, FALSE);
657 /* Handle ServerTLSConnection and ServerAuthentication channels */
658 tp_base_client_take_handler_filter (client, tp_asv_new (
659 /* ChannelType */
660 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
661 TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
662 /* AuthenticationMethod */
663 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
664 TP_HANDLE_TYPE_NONE, NULL));
666 tp_base_client_take_handler_filter (client, tp_asv_new (
667 /* ChannelType */
668 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
669 TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION,
670 /* AuthenticationMethod */
671 TP_PROP_CHANNEL_TYPE_SERVER_AUTHENTICATION_AUTHENTICATION_METHOD,
672 G_TYPE_STRING, TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
673 NULL));
675 /* We are also an observer so that we can see new auth channels
676 * popping up and if we have the password already saved to one
677 * account where an auth channel has just appeared we can call
678 * Claim() on the CDO so the approver won't get it, which makes
679 * sense. */
681 /* Observe ServerAuthentication channels */
682 tp_base_client_take_observer_filter (client, tp_asv_new (
683 /* ChannelType */
684 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
685 TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION,
686 /* AuthenticationMethod */
687 TP_PROP_CHANNEL_TYPE_SERVER_AUTHENTICATION_AUTHENTICATION_METHOD,
688 G_TYPE_STRING, TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
689 NULL));
691 tp_base_client_set_observer_delay_approvers (client, TRUE);
694 static void
695 empathy_auth_factory_dispose (GObject *object)
697 EmpathyAuthFactoryPriv *priv = GET_PRIV (object);
699 if (priv->dispose_run)
700 return;
702 priv->dispose_run = TRUE;
704 g_hash_table_unref (priv->sasl_handlers);
706 #ifdef HAVE_GOA
707 g_object_unref (priv->goa_handler);
708 #endif /* HAVE_GOA */
710 #ifdef HAVE_UOA
711 g_object_unref (priv->uoa_handler);
712 #endif /* HAVE_UOA */
714 g_hash_table_unref (priv->retry_passwords);
716 G_OBJECT_CLASS (empathy_auth_factory_parent_class)->dispose (object);
719 static void
720 empathy_auth_factory_class_init (EmpathyAuthFactoryClass *klass)
722 GObjectClass *oclass = G_OBJECT_CLASS (klass);
723 TpBaseClientClass *base_client_cls = TP_BASE_CLIENT_CLASS (klass);
725 oclass->constructor = empathy_auth_factory_constructor;
726 oclass->constructed = empathy_auth_factory_constructed;
727 oclass->dispose = empathy_auth_factory_dispose;
729 base_client_cls->handle_channels = handle_channels;
730 base_client_cls->observe_channels = observe_channels;
732 g_type_class_add_private (klass, sizeof (EmpathyAuthFactoryPriv));
734 signals[NEW_SERVER_TLS_HANDLER] =
735 g_signal_new ("new-server-tls-handler",
736 G_TYPE_FROM_CLASS (klass),
737 G_SIGNAL_RUN_LAST, 0,
738 NULL, NULL,
739 g_cclosure_marshal_generic,
740 G_TYPE_NONE,
741 1, EMPATHY_TYPE_SERVER_TLS_HANDLER);
743 signals[NEW_SERVER_SASL_HANDLER] =
744 g_signal_new ("new-server-sasl-handler",
745 G_TYPE_FROM_CLASS (klass),
746 G_SIGNAL_RUN_LAST, 0,
747 NULL, NULL,
748 g_cclosure_marshal_generic,
749 G_TYPE_NONE,
750 1, EMPATHY_TYPE_SERVER_SASL_HANDLER);
752 signals[AUTH_PASSWORD_FAILED] =
753 g_signal_new ("auth-password-failed",
754 G_TYPE_FROM_CLASS (klass),
755 G_SIGNAL_RUN_LAST, 0,
756 NULL, NULL,
757 g_cclosure_marshal_generic,
758 G_TYPE_NONE,
759 2, TP_TYPE_ACCOUNT, G_TYPE_STRING);
762 EmpathyAuthFactory *
763 empathy_auth_factory_new (TpSimpleClientFactory *factory)
765 return g_object_new (EMPATHY_TYPE_AUTH_FACTORY,
766 "factory", factory,
767 "name", "Empathy.Auth",
768 NULL);
771 gboolean
772 empathy_auth_factory_register (EmpathyAuthFactory *self,
773 GError **error)
775 return tp_base_client_register (TP_BASE_CLIENT (self), error);
778 void
779 empathy_auth_factory_save_retry_password (EmpathyAuthFactory *self,
780 TpAccount *account,
781 const gchar *password)
783 g_hash_table_insert (self->priv->retry_passwords,
784 g_object_ref (account), g_strdup (password));