]> git.0d.be Git - empathy.git/blob - libempathy/empathy-server-sasl-handler.c
auth-client: improve the password request dialog
[empathy.git] / libempathy / empathy-server-sasl-handler.c
1 /*
2  * empathy-server-sasl-handler.c - Source for EmpathyServerSASLHandler
3  * Copyright (C) 2010 Collabora Ltd.
4  *
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.1 of the License, or (at your option) any later version.
9  *
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.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include "empathy-server-sasl-handler.h"
21
22 #include <telepathy-glib/util.h>
23
24 #define DEBUG_FLAG EMPATHY_DEBUG_SASL
25 #include "empathy-debug.h"
26 #include "empathy-utils.h"
27
28 enum {
29   PROP_CHANNEL = 1,
30   PROP_ACCOUNT,
31   LAST_PROPERTY,
32 };
33
34 /* signal enum */
35 enum {
36   INVALIDATED,
37   LAST_SIGNAL,
38 };
39
40 static guint signals[LAST_SIGNAL] = {0};
41
42 typedef struct {
43   TpChannel *channel;
44   TpAccount *account;
45
46   GSimpleAsyncResult *result;
47 } EmpathyServerSASLHandlerPriv;
48
49 G_DEFINE_TYPE (EmpathyServerSASLHandler, empathy_server_sasl_handler,
50     G_TYPE_OBJECT);
51
52 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyServerSASLHandler);
53
54 static const gchar *sasl_statuses[] = {
55   "not started",
56   "in progress",
57   "server succeeded",
58   "client accepted",
59   "succeeded",
60   "server failed",
61   "client failed",
62 };
63
64 static void
65 sasl_status_changed_cb (TpChannel *channel,
66     TpSASLStatus status,
67     const gchar *error,
68     GHashTable *details,
69     gpointer user_data,
70     GObject *weak_object)
71 {
72   EmpathyServerSASLHandlerPriv *priv = GET_PRIV (weak_object);
73
74   DEBUG ("SASL status changed to '%s'", sasl_statuses[status]);
75
76   if (status == TP_SASL_STATUS_SERVER_SUCCEEDED)
77     {
78       tp_cli_channel_interface_sasl_authentication_call_accept_sasl (
79           priv->channel, -1, NULL, NULL, NULL, NULL);
80
81       tp_cli_channel_call_close (priv->channel, -1,
82           NULL, NULL, NULL, NULL);
83     }
84 }
85
86 static void
87 channel_invalidated_cb (TpProxy *proxy,
88     guint domain,
89     gint code,
90     gchar *message,
91     EmpathyServerSASLHandler *self)
92 {
93   g_signal_emit (self, signals[INVALIDATED], 0);
94 }
95
96 static void
97 empathy_server_sasl_handler_constructed (GObject *object)
98 {
99   EmpathyServerSASLHandlerPriv *priv;
100   GError *error = NULL;
101
102   priv = GET_PRIV (object);
103
104   tp_cli_channel_interface_sasl_authentication_connect_to_sasl_status_changed (priv->channel,
105       sasl_status_changed_cb, NULL, NULL, object, &error);
106
107   if (error != NULL)
108     {
109       DEBUG ("Failed to connect to SASLStatusChanged: %s", error->message);
110       g_clear_error (&error);
111     }
112
113   tp_g_signal_connect_object (priv->channel, "invalidated",
114       G_CALLBACK (channel_invalidated_cb), object, 0);
115 }
116
117 static void
118 empathy_server_sasl_handler_get_property (GObject *object,
119     guint property_id,
120     GValue *value,
121     GParamSpec *pspec)
122 {
123   EmpathyServerSASLHandlerPriv *priv = GET_PRIV (object);
124
125   switch (property_id)
126     {
127     case PROP_CHANNEL:
128       g_value_set_object (value, priv->channel);
129       break;
130     case PROP_ACCOUNT:
131       g_value_set_object (value, priv->account);
132       break;
133     default:
134       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
135       break;
136     }
137 }
138
139 static void
140 empathy_server_sasl_handler_set_property (GObject *object,
141     guint property_id,
142     const GValue *value,
143     GParamSpec *pspec)
144 {
145   EmpathyServerSASLHandlerPriv *priv = GET_PRIV (object);
146
147   switch (property_id)
148     {
149     case PROP_CHANNEL:
150       priv->channel = g_value_dup_object (value);
151       break;
152     case PROP_ACCOUNT:
153       priv->account = g_value_dup_object (value);
154       break;
155     default:
156       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
157       break;
158     }
159 }
160
161 static void
162 empathy_server_sasl_handler_dispose (GObject *object)
163 {
164   EmpathyServerSASLHandlerPriv *priv = GET_PRIV (object);
165
166   DEBUG ("%p", object);
167
168   tp_clear_object (&priv->channel);
169   tp_clear_object (&priv->account);
170
171   G_OBJECT_CLASS (empathy_server_sasl_handler_parent_class)->dispose (object);
172 }
173
174 static void
175 empathy_server_sasl_handler_class_init (EmpathyServerSASLHandlerClass *klass)
176 {
177   GObjectClass *oclass = G_OBJECT_CLASS (klass);
178   GParamSpec *pspec;
179
180   oclass->constructed = empathy_server_sasl_handler_constructed;
181   oclass->get_property = empathy_server_sasl_handler_get_property;
182   oclass->set_property = empathy_server_sasl_handler_set_property;
183   oclass->dispose = empathy_server_sasl_handler_dispose;
184
185   g_type_class_add_private (klass, sizeof (EmpathyServerSASLHandlerPriv));
186
187   pspec = g_param_spec_object ("channel", "The TpChannel",
188       "The TpChannel this handler is supposed to handle.",
189       TP_TYPE_CHANNEL,
190       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
191   g_object_class_install_property (oclass, PROP_CHANNEL, pspec);
192
193   pspec = g_param_spec_object ("account", "The TpAccount",
194       "The TpAccount this channel belongs to.",
195       TP_TYPE_ACCOUNT,
196       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
197   g_object_class_install_property (oclass, PROP_ACCOUNT, pspec);
198
199   signals[INVALIDATED] = g_signal_new ("invalidated",
200       G_TYPE_FROM_CLASS (klass),
201       G_SIGNAL_RUN_LAST, 0,
202       NULL, NULL,
203       g_cclosure_marshal_VOID__VOID,
204       G_TYPE_NONE, 0);
205 }
206
207 static void
208 empathy_server_sasl_handler_init (EmpathyServerSASLHandler *self)
209 {
210   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
211       EMPATHY_TYPE_SERVER_SASL_HANDLER, EmpathyServerSASLHandlerPriv);
212 }
213
214 EmpathyServerSASLHandler *
215 empathy_server_sasl_handler_new (TpAccount *account,
216     TpChannel *channel)
217 {
218   g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
219
220   return g_object_new (EMPATHY_TYPE_SERVER_SASL_HANDLER,
221       "account", account,
222       "channel", channel,
223       NULL);
224 }
225
226 static void
227 start_mechanism_with_data_cb (TpChannel *proxy,
228     const GError *error,
229     gpointer user_data,
230     GObject *weak_object)
231 {
232   if (error != NULL)
233     {
234       DEBUG ("Failed to start mechanism: %s", error->message);
235       return;
236     }
237
238   DEBUG ("Started mechanism successfully");
239 }
240
241 void
242 empathy_server_sasl_handler_provide_password (
243     EmpathyServerSASLHandler *handler,
244     const gchar *password,
245     gboolean remember)
246 {
247   EmpathyServerSASLHandlerPriv *priv;
248   GArray *array;
249
250   g_return_if_fail (EMPATHY_IS_SERVER_SASL_HANDLER (handler));
251
252   priv = GET_PRIV (handler);
253
254   array = g_array_sized_new (TRUE, FALSE,
255       sizeof (gchar), strlen (password));
256
257   g_array_append_vals (array, password, strlen (password));
258
259   DEBUG ("Calling StartMechanismWithData with our password");
260
261   tp_cli_channel_interface_sasl_authentication_call_start_mechanism_with_data (
262       priv->channel, -1, "X-TELEPATHY-PASSWORD", array, start_mechanism_with_data_cb,
263       NULL, NULL, G_OBJECT (handler));
264
265   g_array_unref (array);
266
267   DEBUG ("%sremembering the password", remember ? "" : "not ");
268
269   if (remember)
270     {
271       /* TODO */
272     }
273 }
274
275 void
276 empathy_server_sasl_handler_cancel (EmpathyServerSASLHandler *handler)
277 {
278   EmpathyServerSASLHandlerPriv *priv;
279
280   g_return_if_fail (EMPATHY_IS_SERVER_SASL_HANDLER (handler));
281
282   priv = GET_PRIV (handler);
283
284   DEBUG ("Cancelling SASL mechanism...");
285
286   tp_cli_channel_interface_sasl_authentication_call_abort_sasl (
287       priv->channel, -1, TP_SASL_ABORT_REASON_USER_ABORT,
288       "User cancelled the authentication",
289       NULL, NULL, NULL, NULL);
290 }
291
292 TpAccount *
293 empathy_server_sasl_handler_get_account (EmpathyServerSASLHandler *handler)
294 {
295   EmpathyServerSASLHandlerPriv *priv;
296
297   g_return_val_if_fail (EMPATHY_IS_SERVER_SASL_HANDLER (handler), NULL);
298
299   priv = GET_PRIV (handler);
300
301   return priv->account;
302 }