telepathy: provide certificate data in DER form
[siplcs.git] / src / telepathy / telepathy-tls.c
blobe1b06c1cca12a4344df38f35d9ffa4b5e8430d6a
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 <string.h>
27 #include <glib-object.h>
28 #include <telepathy-glib/dbus-properties-mixin.h>
29 #include <telepathy-glib/svc-channel.h>
30 #include <telepathy-glib/svc-tls.h>
31 #include <telepathy-glib/telepathy-glib.h>
33 #include "sipe-backend.h"
34 #include "sipe-common.h"
36 #include "telepathy-private.h"
38 /* TLS information required for user interaction */
39 struct _SipeTLSCertificate;
40 struct sipe_tls_info {
41 gchar *hostname;
42 gchar *cert_path;
43 GPtrArray *cert_data;
44 GStrv reference_identities;
45 struct _SipeTLSCertificate *certificate;
48 /* Certificate states */
49 #define SIPE_TLS_CERTIFICATE_PENDING 0
50 #define SIPE_TLS_CERTIFICATE_REJECTED 1
51 #define SIPE_TLS_CERTIFICATE_ACCEPTED 2
53 G_BEGIN_DECLS
55 * TLS Manager class - data structures
57 typedef struct _SipeTLSManagerClass {
58 GObjectClass parent_class;
59 } SipeTLSManagerClass;
61 typedef struct _SipeTLSManager {
62 GObject parent;
64 GObject *connection;
66 GSList *channels;
67 } SipeTLSManager;
70 * TLS Manager class - type macros
72 static GType sipe_tls_manager_get_type(void);
73 #define SIPE_TYPE_TLS_MANAGER \
74 (sipe_tls_manager_get_type())
75 #define SIPE_TLS_MANAGER(obj) \
76 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_TLS_MANAGER, \
77 SipeTLSManager))
80 * TLS Channel class - data structures
82 typedef struct _SipeTLSChannelClass {
83 TpBaseChannelClass parent_class;
84 } SipeTLSChannelClass;
86 typedef struct _SipeTLSChannel {
87 TpBaseChannel parent;
89 const struct sipe_tls_info *tls_info;
91 GSimpleAsyncResult *result;
92 } SipeTLSChannel;
95 * TLS Channel class - type macros
97 static GType sipe_tls_channel_get_type(void) G_GNUC_CONST;
98 #define SIPE_TYPE_TLS_CHANNEL \
99 (sipe_tls_channel_get_type())
100 #define SIPE_TLS_CHANNEL(obj) \
101 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_TLS_CHANNEL, \
102 SipeTLSChannel))
105 * TLS Certificate class - data structures
107 typedef struct _SipeTLSCertificateClass {
108 GObjectClass parent_class;
110 TpDBusPropertiesMixinClass dbus_props_class;
111 } SipeTLSCertificateClass;
113 typedef struct _SipeTLSCertificate {
114 GObject parent;
116 const struct sipe_tls_info *tls_info;
118 guint state;
119 } SipeTLSCertificate;
122 * TLS Certificate class - type macros
124 static GType sipe_tls_certificate_get_type(void) G_GNUC_CONST;
125 #define SIPE_TYPE_TLS_CERTIFICATE \
126 (sipe_tls_certificate_get_type())
127 #define SIPE_TLS_CERTIFICATE(obj) \
128 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_TLS_CERTIFICATE, \
129 SipeTLSCertificate))
130 G_END_DECLS
133 * TLS Manager class - type definition
135 static void channel_manager_iface_init(gpointer, gpointer);
136 G_DEFINE_TYPE_WITH_CODE(SipeTLSManager,
137 sipe_tls_manager,
138 G_TYPE_OBJECT,
139 G_IMPLEMENT_INTERFACE(TP_TYPE_CHANNEL_MANAGER,
140 channel_manager_iface_init);
144 * TLS Channel class - type definition
146 G_DEFINE_TYPE_WITH_CODE(SipeTLSChannel,
147 sipe_tls_channel,
148 TP_TYPE_BASE_CHANNEL,
149 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
150 NULL);
154 * TLS Certificate class - type definition
156 static void tls_certificate_iface_init(gpointer, gpointer);
157 G_DEFINE_TYPE_WITH_CODE (SipeTLSCertificate,
158 sipe_tls_certificate,
159 G_TYPE_OBJECT,
160 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_AUTHENTICATION_TLS_CERTIFICATE,
161 tls_certificate_iface_init);
162 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_DBUS_PROPERTIES,
163 tp_dbus_properties_mixin_iface_init);
167 * TLS Manager class - instance methods
169 static void sipe_tls_manager_constructed(GObject *object)
171 SipeTLSManager *self = SIPE_TLS_MANAGER(object);
172 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;
174 if (chain_up)
175 chain_up(object);
177 self->channels = NULL;
180 static void sipe_tls_manager_dispose(GObject *object)
182 SipeTLSManager *self = SIPE_TLS_MANAGER(object);
183 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;
185 tp_clear_object(&self->connection);
187 if (chain_up)
188 chain_up(object);
191 static void sipe_tls_manager_finalize(GObject *object)
193 SipeTLSManager *self = SIPE_TLS_MANAGER(object);
194 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;
195 GSList *entry = self->channels;
197 /* close channels */
198 while (entry) {
199 GSList *next = entry->next;
200 /* removes entry from list */
201 tp_base_channel_close(entry->data);
202 entry = next;
205 tp_clear_object(&self->connection);
207 if (chain_up)
208 chain_up(object);
213 * TLS Manager class - type implementation
215 static void sipe_tls_manager_class_init(SipeTLSManagerClass *klass)
217 GObjectClass *object_class = G_OBJECT_CLASS(klass);
219 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSManager::class_init");
221 object_class->constructed = sipe_tls_manager_constructed;
222 object_class->dispose = sipe_tls_manager_dispose;
223 object_class->finalize = sipe_tls_manager_finalize;
226 static void sipe_tls_manager_init(SIPE_UNUSED_PARAMETER SipeTLSManager *self)
228 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSManager::init");
232 * TLS Manager class - interface implementation
234 * Channel Manager
236 static void foreach_channel(TpChannelManager *manager,
237 TpExportableChannelFunc func,
238 gpointer user_data)
240 SipeTLSManager *self = SIPE_TLS_MANAGER(manager);
241 GSList *entry;
243 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSManager::foreach_channel");
245 for (entry = self->channels; entry; entry = entry->next)
246 func(entry->data, user_data);
249 static void channel_manager_iface_init(gpointer g_iface,
250 SIPE_UNUSED_PARAMETER gpointer iface_data)
252 TpChannelManagerIface *iface = g_iface;
254 #define IMPLEMENT(x, y) iface->x = y
255 IMPLEMENT(foreach_channel, foreach_channel);
256 /* These channels are not requestable. */
257 IMPLEMENT(type_foreach_channel_class, NULL);
258 IMPLEMENT(create_channel, NULL);
259 IMPLEMENT(request_channel, NULL);
260 IMPLEMENT(ensure_channel, NULL);
261 #undef IMPLEMENT
264 /* create new TLS manager object */
265 SipeTLSManager *sipe_telepathy_tls_new(TpBaseConnection *connection)
267 SipeTLSManager *self = g_object_new(SIPE_TYPE_TLS_MANAGER, NULL);
268 self->connection = g_object_ref(connection);
269 return(self);
272 static void channel_closed_cb(SipeTLSChannel *channel,
273 SipeTLSManager *self)
275 SIPE_DEBUG_INFO("channel_closed_cb: %p", channel);
277 self->channels = g_slist_remove(self->channels, channel);
278 tp_channel_manager_emit_channel_closed_for_object(self,
279 TP_EXPORTABLE_CHANNEL(channel));
280 g_object_unref(channel);
283 static void manager_new_channel(SipeTLSManager *self,
284 SipeTLSChannel *channel)
286 self->channels = g_slist_prepend(self->channels,
287 g_object_ref(channel));
289 g_signal_connect(channel,
290 "closed",
291 G_CALLBACK(channel_closed_cb),
292 self);
294 /* emit NewChannel on the ChannelManager iface */
295 tp_channel_manager_emit_new_channel(self,
296 TP_EXPORTABLE_CHANNEL(channel),
297 NULL);
301 * TLS Channel class - instance methods
303 enum {
304 CHANNEL_PROP_SERVER_CERTIFICATE = 1,
305 CHANNEL_PROP_HOSTNAME,
306 CHANNEL_PROP_REFERENCE_IDENTITIES,
307 CHANNEL_LAST_PROP
310 static void channel_get_property(GObject *object,
311 guint property_id,
312 GValue *value,
313 GParamSpec *pspec)
315 SipeTLSChannel *self = SIPE_TLS_CHANNEL(object);
317 switch (property_id) {
318 case CHANNEL_PROP_SERVER_CERTIFICATE:
319 g_value_set_boxed(value, self->tls_info->cert_path);
320 break;
321 case CHANNEL_PROP_HOSTNAME:
322 g_value_set_string(value, self->tls_info->hostname);
323 break;
324 case CHANNEL_PROP_REFERENCE_IDENTITIES:
325 g_value_set_boxed(value, self->tls_info->reference_identities);
326 break;
327 default:
328 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
329 break;
333 static void channel_fill_immutable_properties(TpBaseChannel *channel,
334 GHashTable *properties)
336 TP_BASE_CHANNEL_CLASS(sipe_tls_channel_parent_class)->fill_immutable_properties(channel,
337 properties);
338 tp_dbus_properties_mixin_fill_properties_hash(G_OBJECT(channel),
339 properties,
340 TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ServerCertificate",
341 TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "Hostname",
342 TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ReferenceIdentities",
343 NULL);
346 static gchar *channel_get_object_path_suffix(TpBaseChannel *base)
348 return(g_strdup_printf("TLSChannel_%p", base));
351 static void sipe_tls_channel_constructed(GObject *object)
353 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_channel_parent_class)->constructed;
355 if (chain_up)
356 chain_up(object);
359 static void sipe_tls_channel_finalize(GObject *object)
361 SipeTLSChannel *self = SIPE_TLS_CHANNEL(object);
363 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::finalize");
365 if (self->result) {
366 g_simple_async_result_set_error(self->result,
367 TP_ERROR,
368 TP_ERROR_CANCELLED,
369 "The TLS channel is being destroyed");
370 g_simple_async_result_complete_in_idle(self->result);
371 g_clear_object(&self->result);
374 G_OBJECT_CLASS(sipe_tls_channel_parent_class)->finalize(object);
378 * TLS Channel class - type implementation
380 static void sipe_tls_channel_class_init(SipeTLSChannelClass *klass)
382 static TpDBusPropertiesMixinPropImpl props[] = {
384 .name = "ServerCertificate",
385 .getter_data = "server-certificate",
386 .setter_data = NULL
389 .name = "Hostname",
390 .getter_data = "hostname",
391 .setter_data = NULL
394 .name = "ReferenceIdentities",
395 .getter_data = "reference-identities",
396 .setter_data = NULL
399 .name = NULL
402 GObjectClass *object_class = G_OBJECT_CLASS(klass);
403 TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS(klass);
404 GParamSpec *ps;
406 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::class_init");
408 object_class->constructed = sipe_tls_channel_constructed;
409 object_class->finalize = sipe_tls_channel_finalize;
410 object_class->get_property = channel_get_property;
412 base_class->channel_type = TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION;
413 base_class->target_handle_type = TP_HANDLE_TYPE_NONE;
414 base_class->fill_immutable_properties = channel_fill_immutable_properties;
415 base_class->get_object_path_suffix = channel_get_object_path_suffix;
416 base_class->interfaces = NULL;
417 base_class->close = tp_base_channel_destroyed;
419 ps = g_param_spec_boxed("server-certificate",
420 "Server certificate path",
421 "The object path of the server certificate.",
422 DBUS_TYPE_G_OBJECT_PATH,
423 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
424 g_object_class_install_property(object_class,
425 CHANNEL_PROP_SERVER_CERTIFICATE,
426 ps);
428 ps = g_param_spec_string("hostname",
429 "The hostname to be verified",
430 "The hostname which should be certified by the server certificate.",
431 NULL,
432 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
433 g_object_class_install_property(object_class,
434 CHANNEL_PROP_HOSTNAME,
435 ps);
437 ps = g_param_spec_boxed("reference-identities",
438 "The various identities to check the certificate against",
439 "The server certificate identity should match one of these identities.",
440 G_TYPE_STRV,
441 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
442 g_object_class_install_property(object_class,
443 CHANNEL_PROP_REFERENCE_IDENTITIES,
444 ps);
446 tp_dbus_properties_mixin_implement_interface(object_class,
447 TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
448 tp_dbus_properties_mixin_getter_gobject_properties,
449 NULL,
450 props);
453 static void sipe_tls_channel_init(SIPE_UNUSED_PARAMETER SipeTLSChannel *self)
455 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::init");
458 static void certificate_accepted_cb(SIPE_UNUSED_PARAMETER SipeTLSCertificate *certificate,
459 SipeTLSChannel *self)
461 g_simple_async_result_complete(self->result);
462 g_clear_object(&self->result);
463 tp_base_channel_close(TP_BASE_CHANNEL(self));
466 static void certificate_rejected_cb(SIPE_UNUSED_PARAMETER SipeTLSCertificate *certificate,
467 SIPE_UNUSED_PARAMETER GPtrArray *rejections,
468 SipeTLSChannel *self)
470 static GQuark quark = 0;
472 if (!quark)
473 quark = g_quark_from_static_string("server-tls-error");
475 g_simple_async_result_set_error(self->result,
476 quark,
478 "TLS certificate rejected");
479 g_simple_async_result_complete(self->result);
480 g_clear_object(&self->result);
481 tp_base_channel_close(TP_BASE_CHANNEL(self));
484 static void channel_new_certificate(GObject *connection,
485 struct sipe_tls_info *tls_info,
486 SipeTLSChannel *self,
487 GAsyncReadyCallback callback,
488 gpointer user_data)
490 struct sipe_backend_private *telepathy_private = sipe_telepathy_connection_private(connection);
492 self->tls_info = tls_info;
493 self->result = g_simple_async_result_new(G_OBJECT(self),
494 callback,
495 user_data,
496 channel_new_certificate);
498 g_signal_connect(tls_info->certificate,
499 "accepted",
500 G_CALLBACK(certificate_accepted_cb),
501 self);
503 g_signal_connect(tls_info->certificate,
504 "rejected",
505 G_CALLBACK(certificate_rejected_cb),
506 self);
508 manager_new_channel(telepathy_private->tls_manager, self);
514 * TLS Certificate class - instance methods
516 enum {
517 CERTIFICATE_PROP_OBJECT_PATH = 1,
518 CERTIFICATE_PROP_STATE,
519 CERTIFICATE_PROP_TYPE,
520 CERTIFICATE_PROP_CHAIN_DATA,
521 CERTIFICATE_LAST_PROP
524 static void certificate_get_property(GObject *object,
525 guint property_id,
526 GValue *value,
527 GParamSpec *pspec)
529 SipeTLSCertificate *self = SIPE_TLS_CERTIFICATE(object);
531 switch (property_id) {
532 case CERTIFICATE_PROP_OBJECT_PATH:
533 g_value_set_string(value, self->tls_info->cert_path);
534 break;
535 case CERTIFICATE_PROP_STATE:
536 g_value_set_uint(value, self->state);
537 break;
538 case CERTIFICATE_PROP_TYPE:
539 g_value_set_string(value, "x509");
540 break;
541 case CERTIFICATE_PROP_CHAIN_DATA:
542 g_value_set_boxed(value, self->tls_info->cert_data);
543 break;
544 default:
545 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
546 break;
550 static void sipe_tls_certificate_constructed(GObject *object)
552 SipeTLSCertificate *self = SIPE_TLS_CERTIFICATE(object);
553 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_certificate_parent_class)->constructed;
555 if (chain_up)
556 chain_up(object);
558 self->state = SIPE_TLS_CERTIFICATE_PENDING;
561 static void sipe_tls_certificate_finalize(GObject *object)
563 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::finalize");
565 G_OBJECT_CLASS(sipe_tls_certificate_parent_class)->finalize(object);
569 * TLS Certificate class - type implementation
571 static void sipe_tls_certificate_class_init(SipeTLSCertificateClass *klass)
573 static TpDBusPropertiesMixinPropImpl props[] = {
575 .name = "State",
576 .getter_data = "state",
577 .setter_data = NULL
580 .name = "CertificateType",
581 .getter_data = "certificate-type",
582 .setter_data = NULL
585 .name = "CertificateChainData",
586 .getter_data = "certificate-chain-data",
587 .setter_data = NULL
590 .name = NULL
593 static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
595 .name = TP_IFACE_AUTHENTICATION_TLS_CERTIFICATE,
596 .getter = tp_dbus_properties_mixin_getter_gobject_properties,
597 .setter = NULL,
598 .props = props
601 .name = NULL
604 GObjectClass *object_class = G_OBJECT_CLASS(klass);
605 GParamSpec *ps;
607 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::class_init");
609 klass->dbus_props_class.interfaces = prop_interfaces;
611 object_class->constructed = sipe_tls_certificate_constructed;
612 object_class->finalize = sipe_tls_certificate_finalize;
613 object_class->get_property = certificate_get_property;
615 ps = g_param_spec_string("object-path",
616 "D-Bus object path",
617 "The D-Bus object path used for this object on the bus.",
618 NULL,
619 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
620 g_object_class_install_property(object_class,
621 CERTIFICATE_PROP_OBJECT_PATH,
622 ps);
624 ps = g_param_spec_uint("state",
625 "State of this certificate",
626 "The state of this TLS certificate.",
627 SIPE_TLS_CERTIFICATE_PENDING,
628 SIPE_TLS_CERTIFICATE_ACCEPTED,
629 SIPE_TLS_CERTIFICATE_PENDING,
630 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
631 g_object_class_install_property(object_class,
632 CERTIFICATE_PROP_STATE,
633 ps);
635 ps = g_param_spec_string("certificate-type",
636 "The certificate type",
637 "The type of this certificate.",
638 NULL,
639 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
640 g_object_class_install_property(object_class,
641 CERTIFICATE_PROP_TYPE,
642 ps);
644 ps = g_param_spec_boxed("certificate-chain-data",
645 "The certificate chain data",
646 "The raw DER-encoded trust chain of this certificate.",
647 TP_ARRAY_TYPE_UCHAR_ARRAY_LIST,
648 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
649 g_object_class_install_property(object_class,
650 CERTIFICATE_PROP_CHAIN_DATA, ps);
652 tp_dbus_properties_mixin_class_init(object_class,
653 G_STRUCT_OFFSET(SipeTLSCertificateClass, dbus_props_class));
656 static void sipe_tls_certificate_init(SIPE_UNUSED_PARAMETER SipeTLSCertificate *self)
658 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::init");
662 * TLS Certificate class - interface implementation
664 static void tls_certificate_accept(TpSvcAuthenticationTLSCertificate *certificate,
665 DBusGMethodInvocation *context)
667 SipeTLSCertificate *self = SIPE_TLS_CERTIFICATE(certificate);
669 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::accept");
671 if (self->state != SIPE_TLS_CERTIFICATE_PENDING) {
672 GError error = {
673 TP_ERROR,
674 TP_ERROR_INVALID_ARGUMENT,
675 "Calling Accept() on a certificate with state != PENDING "
676 "doesn't make sense."
679 dbus_g_method_return_error(context, &error);
680 return;
683 self->state = SIPE_TLS_CERTIFICATE_ACCEPTED;
684 tp_svc_authentication_tls_certificate_emit_accepted(self);
686 tp_svc_authentication_tls_certificate_return_from_accept(context);
689 static void tls_certificate_reject(TpSvcAuthenticationTLSCertificate *certificate,
690 const GPtrArray *rejections,
691 DBusGMethodInvocation *context)
693 SipeTLSCertificate *self = SIPE_TLS_CERTIFICATE(certificate);
695 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::reject");
697 if (self->state != SIPE_TLS_CERTIFICATE_PENDING) {
698 GError error = {
699 TP_ERROR,
700 TP_ERROR_INVALID_ARGUMENT,
701 "Calling Reject() on a certificate with state != PENDING "
702 "doesn't make sense."
705 dbus_g_method_return_error(context, &error);
706 return;
709 self->state = SIPE_TLS_CERTIFICATE_REJECTED;
711 tp_svc_authentication_tls_certificate_emit_rejected(self, rejections);
713 tp_svc_authentication_tls_certificate_return_from_reject(context);
716 static void tls_certificate_iface_init(gpointer g_iface,
717 SIPE_UNUSED_PARAMETER gpointer iface_data)
719 TpSvcAuthenticationTLSCertificateClass *klass = g_iface;
721 #define IMPLEMENT(x) \
722 tp_svc_authentication_tls_certificate_implement_##x( \
723 klass, tls_certificate_##x)
724 IMPLEMENT(accept);
725 IMPLEMENT(reject);
726 #undef IMPLEMENT
729 static void append_certificate_der(GPtrArray *certificates,
730 GByteArray *der)
732 GArray *array = g_array_sized_new(FALSE,
733 FALSE,
734 sizeof(guchar),
735 der->len);
736 array = g_array_append_vals(array, der->data, der->len);
737 g_byte_array_unref(der);
739 g_ptr_array_add(certificates, array);
742 struct sipe_tls_info *sipe_telepathy_tls_info_new(const gchar *hostname,
743 GTlsCertificate *certificate)
745 struct sipe_tls_info *tls_info = NULL;
746 GByteArray *der = NULL;
748 g_object_get(certificate, "certificate", &der, NULL);
749 if (der) {
750 GPtrArray *identities = g_ptr_array_new();
752 tls_info = g_new0(struct sipe_tls_info, 1);
753 tls_info->hostname = g_strdup(hostname);
755 /* build GStrv of identies */
756 g_ptr_array_add(identities, g_strdup(hostname));
757 g_ptr_array_add(identities, NULL);
758 tls_info->reference_identities = (GStrv) g_ptr_array_free(identities,
759 FALSE);
761 tls_info->cert_data = g_ptr_array_new_full(1,
762 (GDestroyNotify) g_array_unref);
763 /* unrefs "der" */
764 append_certificate_der(tls_info->cert_data, der);
766 /* will be unref'd in loop */
767 g_object_ref(certificate);
768 while (certificate) {
769 GTlsCertificate *issuer = NULL;
771 g_object_get(certificate, "issuer", &issuer, NULL);
772 g_object_unref(certificate);
774 /* add issuer certificate */
775 if (issuer) {
776 g_object_get(certificate, "certificate", &der, NULL);
777 /* unrefs "der" */
778 if (der)
779 append_certificate_der(tls_info->cert_data, der);
782 /* walk up the chain */
783 certificate = issuer;
787 return(tls_info);
790 void sipe_telepathy_tls_info_free(struct sipe_tls_info *tls_info)
792 g_object_unref(tls_info->certificate);
793 g_free(tls_info->hostname);
794 g_free(tls_info->cert_path);
795 g_ptr_array_unref(tls_info->cert_data);
796 g_strfreev(tls_info->reference_identities);
797 g_free(tls_info);
800 /* create new tls certificate object */
801 void sipe_telepathy_tls_verify_async(GObject *connection,
802 struct sipe_tls_info *tls_info,
803 GAsyncReadyCallback callback,
804 gpointer user_data)
806 /* property "connection" required by TpBaseChannel */
807 SipeTLSChannel *channel = g_object_new(SIPE_TYPE_TLS_CHANNEL,
808 "connection", connection,
809 NULL);
810 TpBaseChannel *base = TP_BASE_CHANNEL(channel);
811 SipeTLSCertificate *certificate = g_object_new(SIPE_TYPE_TLS_CERTIFICATE,
812 NULL);
813 TpDBusDaemon *daemon = tp_dbus_daemon_dup(NULL);
815 tls_info->certificate = certificate;
816 certificate->tls_info = tls_info;
818 tp_base_channel_register(base);
819 tls_info->cert_path = g_strdup_printf("%s/TLSCertificateObject",
820 tp_base_channel_get_object_path(base));
822 /* register the certificate on the bus */
823 tp_dbus_daemon_register_object(daemon,
824 tls_info->cert_path,
825 certificate);
826 g_object_unref(daemon);
828 channel_new_certificate(connection,
829 tls_info,
830 channel,
831 callback,
832 user_data);
836 Local Variables:
837 mode: c
838 c-file-style: "bsd"
839 indent-tabs-mode: t
840 tab-width: 8
841 End: