telepathy: introduce TLS info data structure
[siplcs.git] / src / telepathy / telepathy-tls.c
blob6b689616c20d1168fb82fec5a932e306941da9c7
1 /**
2 * @file telepathy-tls.c
4 * pidgin-sipe
6 * Copyright (C) 2013 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * TLS certificate accept/reject user interaction
25 #include <glib-object.h>
26 #include <telepathy-glib/svc-channel.h>
27 #include <telepathy-glib/telepathy-glib.h>
29 #include "sipe-backend.h"
30 #include "sipe-common.h"
32 #include "telepathy-private.h"
34 /* TLS information required for user interaction */
35 struct sipe_tls_info {
36 gchar *hostname;
37 gchar *server_cert_path;
38 GStrv reference_identities;
41 G_BEGIN_DECLS
43 * TLS Manager class - data structures
45 typedef struct _SipeTLSManagerClass {
46 GObjectClass parent_class;
47 } SipeTLSManagerClass;
49 typedef struct _SipeTLSManager {
50 GObject parent;
52 GObject *connection;
54 GSList *channels;
55 } SipeTLSManager;
58 * TLS Manager class - type macros
60 static GType sipe_tls_manager_get_type(void);
61 #define SIPE_TYPE_TLS_MANAGER \
62 (sipe_tls_manager_get_type())
63 #define SIPE_TLS_MANAGER(obj) \
64 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_TLS_MANAGER, \
65 SipeTLSManager))
68 * TLS Channel class - data structures
70 typedef struct _SipeTLSChannelClass {
71 TpBaseChannelClass parent_class;
72 } SipeTLSChannelClass;
74 typedef struct _SipeTLSChannel {
75 TpBaseChannel parent;
77 const struct sipe_tls_info *tls_info;
79 GSimpleAsyncResult *result;
80 } SipeTLSChannel;
83 * TLS Channel class - type macros
85 static GType sipe_tls_channel_get_type(void) G_GNUC_CONST;
86 #define SIPE_TYPE_TLS_CHANNEL \
87 (sipe_tls_channel_get_type())
88 #define SIPE_TLS_CHANNEL(obj) \
89 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_TLS_CHANNEL, \
90 SipeTLSChannel))
91 G_END_DECLS
94 * TLS Manager class - type definition
96 static void channel_manager_iface_init(gpointer, gpointer);
97 G_DEFINE_TYPE_WITH_CODE(SipeTLSManager,
98 sipe_tls_manager,
99 G_TYPE_OBJECT,
100 G_IMPLEMENT_INTERFACE(TP_TYPE_CHANNEL_MANAGER,
101 channel_manager_iface_init);
105 * TLS Channel class - type definition
107 G_DEFINE_TYPE_WITH_CODE(SipeTLSChannel,
108 sipe_tls_channel,
109 TP_TYPE_BASE_CHANNEL,
110 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
111 NULL);
115 * TLS Manager class - instance methods
117 static void sipe_tls_manager_constructed(GObject *object)
119 SipeTLSManager *self = SIPE_TLS_MANAGER(object);
120 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;
122 if (chain_up)
123 chain_up(object);
125 self->channels = NULL;
128 static void sipe_tls_manager_dispose(GObject *object)
130 SipeTLSManager *self = SIPE_TLS_MANAGER(object);
131 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;
133 tp_clear_object(&self->connection);
135 if (chain_up)
136 chain_up(object);
139 static void sipe_tls_manager_finalize(GObject *object)
141 SipeTLSManager *self = SIPE_TLS_MANAGER(object);
142 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;
143 GSList *entry = self->channels;
145 /* close channels */
146 while (entry) {
147 GSList *next = entry->next;
148 /* removes entry from list */
149 tp_base_channel_close(entry->data);
150 entry = next;
153 tp_clear_object(&self->connection);
155 if (chain_up)
156 chain_up(object);
161 * TLS Manager class - type implementation
163 static void sipe_tls_manager_class_init(SipeTLSManagerClass *klass)
165 GObjectClass *object_class = G_OBJECT_CLASS(klass);
167 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSManager::class_init");
169 object_class->constructed = sipe_tls_manager_constructed;
170 object_class->dispose = sipe_tls_manager_dispose;
171 object_class->finalize = sipe_tls_manager_finalize;
174 static void sipe_tls_manager_init(SIPE_UNUSED_PARAMETER SipeTLSManager *self)
176 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSManager::init");
180 * TLS Manager class - interface implementation
182 * Channel Manager
184 static void foreach_channel(TpChannelManager *manager,
185 TpExportableChannelFunc func,
186 gpointer user_data)
188 SipeTLSManager *self = SIPE_TLS_MANAGER(manager);
190 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSManager::foreach_channel");
192 /* @TODO */
193 (void)self;
194 (void)func;
195 (void)user_data;
198 static void channel_manager_iface_init(gpointer g_iface,
199 SIPE_UNUSED_PARAMETER gpointer iface_data)
201 TpChannelManagerIface *iface = g_iface;
203 #define IMPLEMENT(x, y) iface->x = y
204 IMPLEMENT(foreach_channel, foreach_channel);
205 /* These channels are not requestable. */
206 IMPLEMENT(type_foreach_channel_class, NULL);
207 IMPLEMENT(create_channel, NULL);
208 IMPLEMENT(request_channel, NULL);
209 IMPLEMENT(ensure_channel, NULL);
210 #undef IMPLEMENT
213 /* create new TLS manager object */
214 SipeTLSManager *sipe_telepathy_tls_new(TpBaseConnection *connection)
216 SipeTLSManager *self = g_object_new(SIPE_TYPE_TLS_MANAGER, NULL);
217 self->connection = g_object_ref(connection);
218 return(self);
221 static void channel_closed_cb(SipeTLSChannel *channel,
222 SipeTLSManager *self)
224 self->channels = g_slist_remove(self->channels, channel);
225 tp_channel_manager_emit_channel_closed_for_object(self,
226 TP_EXPORTABLE_CHANNEL(channel));
227 g_object_unref(channel);
230 static void manager_new_channel(SipeTLSManager *self,
231 SipeTLSChannel *channel)
233 self->channels = g_slist_prepend(self->channels,
234 g_object_ref(channel));
236 g_signal_connect(channel,
237 "closed",
238 G_CALLBACK(channel_closed_cb),
239 self);
241 /* emit NewChannel on the ChannelManager iface */
242 tp_channel_manager_emit_new_channel(self,
243 TP_EXPORTABLE_CHANNEL(channel),
244 NULL);
249 * TLS Channel class - instance methods
251 enum {
252 CHANNEL_PROP_SERVER_CERTIFICATE = 1,
253 CHANNEL_PROP_HOSTNAME,
254 CHANNEL_PROP_REFERENCE_IDENTITIES,
255 CHANNEL_LAST_PROP
258 static void get_property(GObject *object,
259 guint property_id,
260 GValue *value,
261 GParamSpec *pspec)
263 SipeTLSChannel *self = SIPE_TLS_CHANNEL(object);
265 switch (property_id) {
266 case CHANNEL_PROP_SERVER_CERTIFICATE:
267 g_value_set_boxed(value, self->tls_info->server_cert_path);
268 break;
269 case CHANNEL_PROP_HOSTNAME:
270 g_value_set_string(value, self->tls_info->hostname);
271 break;
272 case CHANNEL_PROP_REFERENCE_IDENTITIES:
273 g_value_set_boxed(value, self->tls_info->reference_identities);
274 break;
275 default:
276 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
277 break;
281 static void fill_immutable_properties(TpBaseChannel *channel,
282 GHashTable *properties)
284 TP_BASE_CHANNEL_CLASS(sipe_tls_channel_parent_class)->fill_immutable_properties(channel,
285 properties);
286 tp_dbus_properties_mixin_fill_properties_hash(G_OBJECT(channel),
287 properties,
288 TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ServerCertificate",
289 TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "Hostname",
290 TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ReferenceIdentities",
291 NULL);
294 static gchar *get_object_path_suffix(TpBaseChannel *base)
296 return(g_strdup_printf("TLSChannel_%p", base));
299 static void sipe_tls_channel_constructed(GObject *object)
301 SipeTLSChannel *self = SIPE_TLS_CHANNEL(object);
302 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_channel_parent_class)->constructed;
304 if (chain_up)
305 chain_up(object);
307 /* @TODO */
308 (void)self;
311 static void sipe_tls_channel_finalize(GObject *object)
313 SipeTLSChannel *self = SIPE_TLS_CHANNEL(object);
315 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::finalize");
317 g_simple_async_result_complete(self->result);
318 g_clear_object(&self->result);
320 G_OBJECT_CLASS(sipe_tls_channel_parent_class)->finalize(object);
324 * TLS Channel class - type implementation
326 static void sipe_tls_channel_class_init(SipeTLSChannelClass *klass)
328 static TpDBusPropertiesMixinPropImpl props[] = {
330 .name = "ServerCertificate",
331 .getter_data = "server-certificate",
332 .setter_data = NULL
335 .name = "Hostname",
336 .getter_data = "hostname",
337 .setter_data = NULL
340 .name = "ReferenceIdentities",
341 .getter_data = "reference-identities",
342 .setter_data = NULL
345 .name = NULL
348 GObjectClass *object_class = G_OBJECT_CLASS(klass);
349 TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS(klass);
350 GParamSpec *ps;
352 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::class_init");
354 object_class->constructed = sipe_tls_channel_constructed;
355 object_class->finalize = sipe_tls_channel_finalize;
356 object_class->get_property = get_property;
358 base_class->channel_type = TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION;
359 base_class->target_handle_type = TP_HANDLE_TYPE_NONE;
360 base_class->fill_immutable_properties = fill_immutable_properties;
361 base_class->get_object_path_suffix = get_object_path_suffix;
362 base_class->interfaces = NULL;
363 base_class->close = tp_base_channel_destroyed;
365 ps = g_param_spec_boxed("server-certificate",
366 "Server certificate path",
367 "The object path of the server certificate.",
368 DBUS_TYPE_G_OBJECT_PATH,
369 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
370 g_object_class_install_property(object_class,
371 CHANNEL_PROP_SERVER_CERTIFICATE,
372 ps);
374 ps = g_param_spec_string("hostname",
375 "The hostname to be verified",
376 "The hostname which should be certified by the server certificate.",
377 NULL,
378 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
379 g_object_class_install_property(object_class,
380 CHANNEL_PROP_HOSTNAME,
381 ps);
383 ps = g_param_spec_boxed("reference-identities",
384 "The various identities to check the certificate against",
385 "The server certificate identity should match one of these identities.",
386 G_TYPE_STRV,
387 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
388 g_object_class_install_property(object_class,
389 CHANNEL_PROP_REFERENCE_IDENTITIES,
390 ps);
392 tp_dbus_properties_mixin_implement_interface(object_class,
393 TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
394 tp_dbus_properties_mixin_getter_gobject_properties,
395 NULL,
396 props);
399 static void sipe_tls_channel_init(SIPE_UNUSED_PARAMETER SipeTLSChannel *self)
401 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::init");
404 struct sipe_tls_info *sipe_telepathy_tls_info_new(const gchar *hostname,
405 SIPE_UNUSED_PARAMETER struct _GTlsCertificate *certificate)
407 struct sipe_tls_info *tls_info = g_new0(struct sipe_tls_info, 1);
409 tls_info->hostname = g_strdup(hostname);
412 * @TODO
413 * tls_info->reference_identities = g_boxed_copy(G_TYPE_STRV, reference_identities);??
414 * tls_info->tls_info->server_cert_path
417 return(tls_info);
420 void sipe_telepathy_tls_info_free(struct sipe_tls_info *tls_info)
422 g_free(tls_info->hostname);
423 g_free(tls_info->server_cert_path);
424 g_strfreev(tls_info->reference_identities);
425 g_free(tls_info);
428 /* create new tls channel object */
429 void sipe_telepathy_tls_verify_async(GObject *connection,
430 struct sipe_tls_info *tls_info,
431 GAsyncReadyCallback callback,
432 gpointer user_data)
434 struct sipe_backend_private *telepathy_private = sipe_telepathy_connection_private(connection);
436 /* property "connection" required by TpBaseChannel */
437 SipeTLSChannel *self = g_object_new(SIPE_TYPE_TLS_CHANNEL,
438 "connection", connection,
439 NULL);
441 self->tls_info = tls_info;
442 self->result = g_simple_async_result_new(G_OBJECT(self),
443 callback,
444 user_data,
445 sipe_telepathy_tls_verify_async);
447 tp_base_channel_register(TP_BASE_CHANNEL(self));
449 manager_new_channel(telepathy_private->tls_manager, self);
453 Local Variables:
454 mode: c
455 c-file-style: "bsd"
456 indent-tabs-mode: t
457 tab-width: 8
458 End: