]> git.0d.be Git - empathy.git/blob - libempathy/empathy-server-tls-handler.c
Merge branch 'sasl'
[empathy.git] / libempathy / empathy-server-tls-handler.c
1 /*
2  * empathy-server-tls-handler.c - Source for EmpathyServerTLSHandler
3  * Copyright (C) 2010 Collabora Ltd.
4  * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "empathy-server-tls-handler.h"
22
23 #include <telepathy-glib/util.h>
24
25 #define DEBUG_FLAG EMPATHY_DEBUG_TLS
26 #include "empathy-debug.h"
27 #include "empathy-tls-certificate.h"
28 #include "empathy-utils.h"
29
30 #include "extensions/extensions.h"
31
32 static void async_initable_iface_init (GAsyncInitableIface *iface);
33
34 enum {
35   PROP_CHANNEL = 1,
36   PROP_TLS_CERTIFICATE,
37   PROP_HOSTNAME,
38   LAST_PROPERTY,
39 };
40
41 typedef struct {
42   TpChannel *channel;
43
44   EmpathyTLSCertificate *certificate;
45   gchar *hostname;
46
47   GSimpleAsyncResult *async_init_res;
48 } EmpathyServerTLSHandlerPriv;
49
50 G_DEFINE_TYPE_WITH_CODE (EmpathyServerTLSHandler, empathy_server_tls_handler,
51     G_TYPE_OBJECT,
52     G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init));
53
54 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyServerTLSHandler);
55
56 static void
57 tls_certificate_prepared_cb (GObject *source,
58     GAsyncResult *result,
59     gpointer user_data)
60 {
61   EmpathyTLSCertificate *certificate = EMPATHY_TLS_CERTIFICATE (source);
62   EmpathyServerTLSHandler *self = user_data;
63   GError *error = NULL;
64   EmpathyServerTLSHandlerPriv *priv = GET_PRIV (self);
65
66   empathy_tls_certificate_prepare_finish (certificate, result, &error);
67
68   if (error != NULL)
69     {
70       g_simple_async_result_set_from_error (priv->async_init_res, error);
71       g_error_free (error);
72     }
73
74   g_simple_async_result_complete_in_idle (priv->async_init_res);
75   tp_clear_object (&priv->async_init_res);
76 }
77
78 static gboolean
79 tls_handler_init_finish (GAsyncInitable *initable,
80     GAsyncResult *res,
81     GError **error)
82 {
83   gboolean retval = TRUE;
84
85   if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res),
86           error))
87     retval = FALSE;
88
89   return retval;
90 }
91
92 static void
93 tls_handler_init_async (GAsyncInitable *initable,
94     gint io_priority,
95     GCancellable *cancellable,
96     GAsyncReadyCallback callback,
97     gpointer user_data)
98 {
99   GHashTable *properties;
100   const gchar *cert_object_path;
101   const gchar *hostname;
102   const gchar *bus_name;
103   TpDBusDaemon *dbus;
104   GError *error = NULL;
105   EmpathyServerTLSHandler *self = EMPATHY_SERVER_TLS_HANDLER (initable);
106   EmpathyServerTLSHandlerPriv *priv = GET_PRIV (self);
107
108   g_assert (priv->channel != NULL);
109
110   priv->async_init_res = g_simple_async_result_new (G_OBJECT (self),
111       callback, user_data, empathy_server_tls_handler_new_async);
112   properties = tp_channel_borrow_immutable_properties (priv->channel);
113
114   hostname = tp_asv_get_string (properties,
115       EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION ".Hostname");
116   priv->hostname = g_strdup (hostname);
117
118   DEBUG ("Received hostname: %s", hostname);
119
120   cert_object_path = tp_asv_get_object_path (properties,
121       EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION ".ServerCertificate");
122   bus_name = tp_proxy_get_bus_name (TP_PROXY (priv->channel));
123   dbus = tp_proxy_get_dbus_daemon (TP_PROXY (priv->channel));
124
125   DEBUG ("Creating an EmpathyTLSCertificate for path %s, bus name %s",
126       cert_object_path, bus_name);
127
128   priv->certificate = empathy_tls_certificate_new (dbus, bus_name,
129       cert_object_path, &error);
130
131   if (error != NULL)
132     {
133       DEBUG ("Unable to create the EmpathyTLSCertificate: error %s",
134           error->message);
135
136       g_simple_async_result_set_from_error (priv->async_init_res, error);
137       g_simple_async_result_complete_in_idle (priv->async_init_res);
138
139       g_error_free (error);
140       tp_clear_object (&priv->async_init_res);
141
142       return;
143     }
144
145   empathy_tls_certificate_prepare_async (priv->certificate,
146       tls_certificate_prepared_cb, self);
147 }
148
149 static void
150 async_initable_iface_init (GAsyncInitableIface *iface)
151 {
152   iface->init_async = tls_handler_init_async;
153   iface->init_finish = tls_handler_init_finish;
154 }
155
156 static void
157 empathy_server_tls_handler_finalize (GObject *object)
158 {
159   EmpathyServerTLSHandlerPriv *priv = GET_PRIV (object);
160
161   DEBUG ("%p", object);
162
163   tp_clear_object (&priv->channel);
164   tp_clear_object (&priv->certificate);
165
166   G_OBJECT_CLASS (empathy_server_tls_handler_parent_class)->finalize (object);
167 }
168
169 static void
170 empathy_server_tls_handler_get_property (GObject *object,
171     guint property_id,
172     GValue *value,
173     GParamSpec *pspec)
174 {
175   EmpathyServerTLSHandlerPriv *priv = GET_PRIV (object);
176
177   switch (property_id)
178     {
179     case PROP_CHANNEL:
180       g_value_set_object (value, priv->channel);
181       break;
182     case PROP_TLS_CERTIFICATE:
183       g_value_set_object (value, priv->certificate);
184       break;
185     case PROP_HOSTNAME:
186       g_value_set_string (value, priv->hostname);
187       break;
188     default:
189       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
190       break;
191     }
192 }
193
194 static void
195 empathy_server_tls_handler_set_property (GObject *object,
196     guint property_id,
197     const GValue *value,
198     GParamSpec *pspec)
199 {
200   EmpathyServerTLSHandlerPriv *priv = GET_PRIV (object);
201
202   switch (property_id)
203     {
204     case PROP_CHANNEL:
205       priv->channel = g_value_dup_object (value);
206       break;
207     default:
208       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
209       break;
210     }
211 }
212
213 static void
214 empathy_server_tls_handler_class_init (EmpathyServerTLSHandlerClass *klass)
215 {
216   GObjectClass *oclass = G_OBJECT_CLASS (klass);
217   GParamSpec *pspec;
218
219   oclass->get_property = empathy_server_tls_handler_get_property;
220   oclass->set_property = empathy_server_tls_handler_set_property;
221   oclass->finalize = empathy_server_tls_handler_finalize;
222
223   g_type_class_add_private (klass, sizeof (EmpathyServerTLSHandlerPriv));
224
225   pspec = g_param_spec_object ("channel", "The TpChannel",
226       "The TpChannel this handler is supposed to handle.",
227       TP_TYPE_CHANNEL,
228       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
229   g_object_class_install_property (oclass, PROP_CHANNEL, pspec);
230
231   pspec = g_param_spec_object ("certificate", "The EmpathyTLSCertificate",
232       "The EmpathyTLSCertificate carried by the channel.",
233       EMPATHY_TYPE_TLS_CERTIFICATE,
234       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
235   g_object_class_install_property (oclass, PROP_TLS_CERTIFICATE, pspec);
236
237   pspec = g_param_spec_string ("hostname", "The hostname",
238       "The hostname which should be certified by the server certificate.",
239       NULL,
240       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
241   g_object_class_install_property (oclass, PROP_HOSTNAME, pspec);
242 }
243
244 static void
245 empathy_server_tls_handler_init (EmpathyServerTLSHandler *self)
246 {
247   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
248       EMPATHY_TYPE_SERVER_TLS_HANDLER, EmpathyServerTLSHandlerPriv);
249 }
250
251 void
252 empathy_server_tls_handler_new_async (TpChannel *channel,
253     GAsyncReadyCallback callback,
254     gpointer user_data)
255 {
256   g_assert (TP_IS_CHANNEL (channel));
257   g_assert (channel != NULL);
258
259   g_async_initable_new_async (EMPATHY_TYPE_SERVER_TLS_HANDLER,
260       G_PRIORITY_DEFAULT, NULL, callback, user_data,
261       "channel", channel, NULL);
262 }
263
264 EmpathyServerTLSHandler *
265 empathy_server_tls_handler_new_finish (GAsyncResult *result,
266     GError **error)
267 {
268   GObject *object, *source_object;
269
270   source_object = g_async_result_get_source_object (result);
271
272   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
273       result, error);
274   g_object_unref (source_object);
275
276   if (object != NULL)
277     return EMPATHY_SERVER_TLS_HANDLER (object);
278   else
279     return NULL;
280 }
281
282 EmpathyTLSCertificate *
283 empathy_server_tls_handler_get_certificate (EmpathyServerTLSHandler *self)
284 {
285   EmpathyServerTLSHandlerPriv *priv = GET_PRIV (self);
286
287   g_assert (priv->certificate != NULL);
288
289   return priv->certificate;
290 }