Release 1.25.0 -- Buddy Idle Time, RTF
[siplcs.git] / src / telepathy / telepathy-tls.c
blob26710bd0db7fae101d4773e082dc61a6746bc58f
1 /**
2 * @file telepathy-tls.c
4 * pidgin-sipe
6 * Copyright (C) 2013-2018 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 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
29 #include <string.h>
31 #include <glib-object.h>
32 #include <telepathy-glib/dbus-properties-mixin.h>
33 #include <telepathy-glib/svc-channel.h>
34 #include <telepathy-glib/svc-tls.h>
35 #include <telepathy-glib/telepathy-glib.h>
37 #include "sipe-backend.h"
38 #include "sipe-common.h"
40 #include "telepathy-private.h"
42 /* TLS information required for user interaction */
43 struct _SipeTLSCertificate;
44 struct sipe_tls_info {
45 gchar *hostname;
46 gchar *cert_path;
47 GPtrArray *cert_data;
48 GStrv reference_identities;
49 struct _SipeTLSCertificate *certificate;
52 /* Certificate states */
53 #define SIPE_TLS_CERTIFICATE_PENDING 0
54 #define SIPE_TLS_CERTIFICATE_REJECTED 1
55 #define SIPE_TLS_CERTIFICATE_ACCEPTED 2
57 G_BEGIN_DECLS
59 * TLS Manager class - data structures
61 typedef struct _SipeTLSManagerClass {
62 GObjectClass parent_class;
63 } SipeTLSManagerClass;
65 typedef struct _SipeTLSManager {
66 GObject parent;
68 GObject *connection;
70 GSList *channels;
71 } SipeTLSManager;
74 * TLS Manager class - type macros
76 static GType sipe_tls_manager_get_type(void);
77 #define SIPE_TYPE_TLS_MANAGER \
78 (sipe_tls_manager_get_type())
79 #define SIPE_TLS_MANAGER(obj) \
80 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_TLS_MANAGER, \
81 SipeTLSManager))
84 * TLS Channel class - data structures
86 typedef struct _SipeTLSChannelClass {
87 TpBaseChannelClass parent_class;
88 } SipeTLSChannelClass;
90 typedef struct _SipeTLSChannel {
91 TpBaseChannel parent;
93 const struct sipe_tls_info *tls_info;
95 GSimpleAsyncResult *result;
96 } SipeTLSChannel;
99 * TLS Channel class - type macros
101 static GType sipe_tls_channel_get_type(void) G_GNUC_CONST;
102 #define SIPE_TYPE_TLS_CHANNEL \
103 (sipe_tls_channel_get_type())
104 #define SIPE_TLS_CHANNEL(obj) \
105 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_TLS_CHANNEL, \
106 SipeTLSChannel))
109 * TLS Certificate class - data structures
111 typedef struct _SipeTLSCertificateClass {
112 GObjectClass parent_class;
114 TpDBusPropertiesMixinClass dbus_props_class;
115 } SipeTLSCertificateClass;
117 typedef struct _SipeTLSCertificate {
118 GObject parent;
120 const struct sipe_tls_info *tls_info;
122 guint state;
123 } SipeTLSCertificate;
126 * TLS Certificate class - type macros
128 static GType sipe_tls_certificate_get_type(void) G_GNUC_CONST;
129 #define SIPE_TYPE_TLS_CERTIFICATE \
130 (sipe_tls_certificate_get_type())
131 #define SIPE_TLS_CERTIFICATE(obj) \
132 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_TLS_CERTIFICATE, \
133 SipeTLSCertificate))
134 G_END_DECLS
137 * TLS Manager class - type definition
139 static void channel_manager_iface_init(gpointer, gpointer);
140 G_DEFINE_TYPE_WITH_CODE(SipeTLSManager,
141 sipe_tls_manager,
142 G_TYPE_OBJECT,
143 G_IMPLEMENT_INTERFACE(TP_TYPE_CHANNEL_MANAGER,
144 channel_manager_iface_init);
148 * TLS Channel class - type definition
150 G_DEFINE_TYPE_WITH_CODE(SipeTLSChannel,
151 sipe_tls_channel,
152 TP_TYPE_BASE_CHANNEL,
153 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
154 NULL);
158 * TLS Certificate class - type definition
160 static void tls_certificate_iface_init(gpointer, gpointer);
161 G_DEFINE_TYPE_WITH_CODE (SipeTLSCertificate,
162 sipe_tls_certificate,
163 G_TYPE_OBJECT,
164 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_AUTHENTICATION_TLS_CERTIFICATE,
165 tls_certificate_iface_init);
166 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_DBUS_PROPERTIES,
167 tp_dbus_properties_mixin_iface_init);
171 * TLS Manager class - instance methods
173 static void sipe_tls_manager_constructed(GObject *object)
175 SipeTLSManager *self = SIPE_TLS_MANAGER(object);
176 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;
178 if (chain_up)
179 chain_up(object);
181 self->channels = NULL;
184 static void sipe_tls_manager_dispose(GObject *object)
186 SipeTLSManager *self = SIPE_TLS_MANAGER(object);
187 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;
189 tp_clear_object(&self->connection);
191 if (chain_up)
192 chain_up(object);
195 static void sipe_tls_manager_finalize(GObject *object)
197 SipeTLSManager *self = SIPE_TLS_MANAGER(object);
198 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;
199 GSList *entry = self->channels;
201 /* close channels */
202 while (entry) {
203 GSList *next = entry->next;
204 /* removes entry from list */
205 tp_base_channel_close(entry->data);
206 entry = next;
209 tp_clear_object(&self->connection);
211 if (chain_up)
212 chain_up(object);
217 * TLS Manager class - type implementation
219 static void sipe_tls_manager_class_init(SipeTLSManagerClass *klass)
221 GObjectClass *object_class = G_OBJECT_CLASS(klass);
223 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSManager::class_init");
225 object_class->constructed = sipe_tls_manager_constructed;
226 object_class->dispose = sipe_tls_manager_dispose;
227 object_class->finalize = sipe_tls_manager_finalize;
230 static void sipe_tls_manager_init(SIPE_UNUSED_PARAMETER SipeTLSManager *self)
232 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSManager::init");
236 * TLS Manager class - interface implementation
238 * Channel Manager
240 static void foreach_channel(TpChannelManager *manager,
241 TpExportableChannelFunc func,
242 gpointer user_data)
244 SipeTLSManager *self = SIPE_TLS_MANAGER(manager);
245 GSList *entry;
247 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSManager::foreach_channel");
249 for (entry = self->channels; entry; entry = entry->next)
250 func(entry->data, user_data);
253 static void channel_manager_iface_init(gpointer g_iface,
254 SIPE_UNUSED_PARAMETER gpointer iface_data)
256 TpChannelManagerIface *iface = g_iface;
258 #define IMPLEMENT(x, y) iface->x = y
259 IMPLEMENT(foreach_channel, foreach_channel);
260 /* These channels are not requestable. */
261 IMPLEMENT(type_foreach_channel_class, NULL);
262 IMPLEMENT(create_channel, NULL);
263 IMPLEMENT(request_channel, NULL);
264 IMPLEMENT(ensure_channel, NULL);
265 #undef IMPLEMENT
268 /* create new TLS manager object */
269 SipeTLSManager *sipe_telepathy_tls_new(TpBaseConnection *connection)
271 SipeTLSManager *self = g_object_new(SIPE_TYPE_TLS_MANAGER, NULL);
272 self->connection = g_object_ref(G_OBJECT(connection));
273 return(self);
276 static void channel_closed_cb(SipeTLSChannel *channel,
277 SipeTLSManager *self)
279 SIPE_DEBUG_INFO("channel_closed_cb: %p", channel);
281 self->channels = g_slist_remove(self->channels, channel);
282 tp_channel_manager_emit_channel_closed_for_object(self,
283 TP_EXPORTABLE_CHANNEL(channel));
284 g_object_unref(channel);
287 static void manager_new_channel(SipeTLSManager *self,
288 SipeTLSChannel *channel)
290 self->channels = g_slist_prepend(self->channels,
291 g_object_ref(channel));
293 g_signal_connect(channel,
294 "closed",
295 G_CALLBACK(channel_closed_cb),
296 self);
298 /* emit NewChannel on the ChannelManager iface */
299 tp_channel_manager_emit_new_channel(self,
300 TP_EXPORTABLE_CHANNEL(channel),
301 NULL);
305 * TLS Channel class - instance methods
307 enum {
308 CHANNEL_PROP_SERVER_CERTIFICATE = 1,
309 CHANNEL_PROP_HOSTNAME,
310 CHANNEL_PROP_REFERENCE_IDENTITIES,
311 CHANNEL_LAST_PROP
314 static void channel_get_property(GObject *object,
315 guint property_id,
316 GValue *value,
317 GParamSpec *pspec)
319 SipeTLSChannel *self = SIPE_TLS_CHANNEL(object);
321 switch (property_id) {
322 case CHANNEL_PROP_SERVER_CERTIFICATE:
323 g_value_set_boxed(value, self->tls_info->cert_path);
324 break;
325 case CHANNEL_PROP_HOSTNAME:
326 g_value_set_string(value, self->tls_info->hostname);
327 break;
328 case CHANNEL_PROP_REFERENCE_IDENTITIES:
329 g_value_set_boxed(value, self->tls_info->reference_identities);
330 break;
331 default:
332 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
333 break;
337 static void channel_fill_immutable_properties(TpBaseChannel *channel,
338 GHashTable *properties)
340 TP_BASE_CHANNEL_CLASS(sipe_tls_channel_parent_class)->fill_immutable_properties(channel,
341 properties);
342 tp_dbus_properties_mixin_fill_properties_hash(G_OBJECT(channel),
343 properties,
344 TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ServerCertificate",
345 TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "Hostname",
346 TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ReferenceIdentities",
347 NULL);
350 static gchar *channel_get_object_path_suffix(TpBaseChannel *base)
352 return(g_strdup_printf("TLSChannel_%p", base));
355 static void sipe_tls_channel_constructed(GObject *object)
357 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_channel_parent_class)->constructed;
359 if (chain_up)
360 chain_up(object);
363 static void sipe_tls_channel_finalize(GObject *object)
365 SipeTLSChannel *self = SIPE_TLS_CHANNEL(object);
367 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::finalize");
369 if (self->result) {
370 g_simple_async_result_set_error(self->result,
371 TP_ERROR,
372 TP_ERROR_CANCELLED,
373 "The TLS channel is being destroyed");
374 g_simple_async_result_complete_in_idle(self->result);
375 g_clear_object(&self->result);
378 G_OBJECT_CLASS(sipe_tls_channel_parent_class)->finalize(object);
382 * TLS Channel class - type implementation
384 static void sipe_tls_channel_class_init(SipeTLSChannelClass *klass)
386 static TpDBusPropertiesMixinPropImpl props[] = {
388 .name = "ServerCertificate",
389 .getter_data = "server-certificate",
390 .setter_data = NULL
393 .name = "Hostname",
394 .getter_data = "hostname",
395 .setter_data = NULL
398 .name = "ReferenceIdentities",
399 .getter_data = "reference-identities",
400 .setter_data = NULL
403 .name = NULL
406 GObjectClass *object_class = G_OBJECT_CLASS(klass);
407 TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS(klass);
408 GParamSpec *ps;
410 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::class_init");
412 object_class->constructed = sipe_tls_channel_constructed;
413 object_class->finalize = sipe_tls_channel_finalize;
414 object_class->get_property = channel_get_property;
416 base_class->channel_type = TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION;
417 base_class->target_handle_type = TP_HANDLE_TYPE_NONE;
418 base_class->fill_immutable_properties = channel_fill_immutable_properties;
419 base_class->get_object_path_suffix = channel_get_object_path_suffix;
420 base_class->interfaces = NULL;
421 base_class->close = tp_base_channel_destroyed;
423 ps = g_param_spec_boxed("server-certificate",
424 "Server certificate path",
425 "The object path of the server certificate.",
426 DBUS_TYPE_G_OBJECT_PATH,
427 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
428 g_object_class_install_property(object_class,
429 CHANNEL_PROP_SERVER_CERTIFICATE,
430 ps);
432 ps = g_param_spec_string("hostname",
433 "The hostname to be verified",
434 "The hostname which should be certified by the server certificate.",
435 NULL,
436 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
437 g_object_class_install_property(object_class,
438 CHANNEL_PROP_HOSTNAME,
439 ps);
441 ps = g_param_spec_boxed("reference-identities",
442 "The various identities to check the certificate against",
443 "The server certificate identity should match one of these identities.",
444 G_TYPE_STRV,
445 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
446 g_object_class_install_property(object_class,
447 CHANNEL_PROP_REFERENCE_IDENTITIES,
448 ps);
450 tp_dbus_properties_mixin_implement_interface(object_class,
451 TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
452 tp_dbus_properties_mixin_getter_gobject_properties,
453 NULL,
454 props);
457 static void sipe_tls_channel_init(SIPE_UNUSED_PARAMETER SipeTLSChannel *self)
459 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::init");
462 static void certificate_accepted_cb(SIPE_UNUSED_PARAMETER SipeTLSCertificate *certificate,
463 SipeTLSChannel *self)
465 g_simple_async_result_complete(self->result);
466 g_clear_object(&self->result);
467 tp_base_channel_close(TP_BASE_CHANNEL(self));
470 static void certificate_rejected_cb(SIPE_UNUSED_PARAMETER SipeTLSCertificate *certificate,
471 SIPE_UNUSED_PARAMETER GPtrArray *rejections,
472 SipeTLSChannel *self)
474 static GQuark quark = 0;
476 if (!quark)
477 quark = g_quark_from_static_string("server-tls-error");
479 g_simple_async_result_set_error(self->result,
480 quark,
482 "TLS certificate rejected");
483 g_simple_async_result_complete(self->result);
484 g_clear_object(&self->result);
485 tp_base_channel_close(TP_BASE_CHANNEL(self));
488 static void channel_new_certificate(GObject *connection,
489 struct sipe_tls_info *tls_info,
490 SipeTLSChannel *self,
491 GAsyncReadyCallback callback,
492 gpointer user_data)
494 struct sipe_backend_private *telepathy_private = sipe_telepathy_connection_private(connection);
496 self->tls_info = tls_info;
497 self->result = g_simple_async_result_new(G_OBJECT(self),
498 callback,
499 user_data,
500 channel_new_certificate);
502 g_signal_connect(tls_info->certificate,
503 "accepted",
504 G_CALLBACK(certificate_accepted_cb),
505 self);
507 g_signal_connect(tls_info->certificate,
508 "rejected",
509 G_CALLBACK(certificate_rejected_cb),
510 self);
512 manager_new_channel(telepathy_private->tls_manager, self);
518 * TLS Certificate class - instance methods
520 enum {
521 CERTIFICATE_PROP_OBJECT_PATH = 1,
522 CERTIFICATE_PROP_STATE,
523 CERTIFICATE_PROP_TYPE,
524 CERTIFICATE_PROP_CHAIN_DATA,
525 CERTIFICATE_LAST_PROP
528 static void certificate_get_property(GObject *object,
529 guint property_id,
530 GValue *value,
531 GParamSpec *pspec)
533 SipeTLSCertificate *self = SIPE_TLS_CERTIFICATE(object);
535 switch (property_id) {
536 case CERTIFICATE_PROP_OBJECT_PATH:
537 g_value_set_string(value, self->tls_info->cert_path);
538 break;
539 case CERTIFICATE_PROP_STATE:
540 g_value_set_uint(value, self->state);
541 break;
542 case CERTIFICATE_PROP_TYPE:
543 g_value_set_string(value, "x509");
544 break;
545 case CERTIFICATE_PROP_CHAIN_DATA:
546 g_value_set_boxed(value, self->tls_info->cert_data);
547 break;
548 default:
549 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
550 break;
554 static void sipe_tls_certificate_constructed(GObject *object)
556 SipeTLSCertificate *self = SIPE_TLS_CERTIFICATE(object);
557 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_certificate_parent_class)->constructed;
559 if (chain_up)
560 chain_up(object);
562 self->state = SIPE_TLS_CERTIFICATE_PENDING;
565 static void sipe_tls_certificate_finalize(GObject *object)
567 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::finalize");
569 G_OBJECT_CLASS(sipe_tls_certificate_parent_class)->finalize(object);
573 * TLS Certificate class - type implementation
575 static void sipe_tls_certificate_class_init(SipeTLSCertificateClass *klass)
577 static TpDBusPropertiesMixinPropImpl props[] = {
579 .name = "State",
580 .getter_data = "state",
581 .setter_data = NULL
584 .name = "CertificateType",
585 .getter_data = "certificate-type",
586 .setter_data = NULL
589 .name = "CertificateChainData",
590 .getter_data = "certificate-chain-data",
591 .setter_data = NULL
594 .name = NULL
597 static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
599 .name = TP_IFACE_AUTHENTICATION_TLS_CERTIFICATE,
600 .getter = tp_dbus_properties_mixin_getter_gobject_properties,
601 .setter = NULL,
602 .props = props
605 .name = NULL
608 GObjectClass *object_class = G_OBJECT_CLASS(klass);
609 GParamSpec *ps;
611 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::class_init");
613 klass->dbus_props_class.interfaces = prop_interfaces;
615 object_class->constructed = sipe_tls_certificate_constructed;
616 object_class->finalize = sipe_tls_certificate_finalize;
617 object_class->get_property = certificate_get_property;
619 ps = g_param_spec_string("object-path",
620 "D-Bus object path",
621 "The D-Bus object path used for this object on the bus.",
622 NULL,
623 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
624 g_object_class_install_property(object_class,
625 CERTIFICATE_PROP_OBJECT_PATH,
626 ps);
628 ps = g_param_spec_uint("state",
629 "State of this certificate",
630 "The state of this TLS certificate.",
631 SIPE_TLS_CERTIFICATE_PENDING,
632 SIPE_TLS_CERTIFICATE_ACCEPTED,
633 SIPE_TLS_CERTIFICATE_PENDING,
634 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
635 g_object_class_install_property(object_class,
636 CERTIFICATE_PROP_STATE,
637 ps);
639 ps = g_param_spec_string("certificate-type",
640 "The certificate type",
641 "The type of this certificate.",
642 NULL,
643 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
644 g_object_class_install_property(object_class,
645 CERTIFICATE_PROP_TYPE,
646 ps);
648 ps = g_param_spec_boxed("certificate-chain-data",
649 "The certificate chain data",
650 "The raw DER-encoded trust chain of this certificate.",
651 TP_ARRAY_TYPE_UCHAR_ARRAY_LIST,
652 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
653 g_object_class_install_property(object_class,
654 CERTIFICATE_PROP_CHAIN_DATA, ps);
656 tp_dbus_properties_mixin_class_init(object_class,
657 G_STRUCT_OFFSET(SipeTLSCertificateClass, dbus_props_class));
660 static void sipe_tls_certificate_init(SIPE_UNUSED_PARAMETER SipeTLSCertificate *self)
662 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::init");
666 * TLS Certificate class - interface implementation
668 static void tls_certificate_accept(TpSvcAuthenticationTLSCertificate *certificate,
669 DBusGMethodInvocation *context)
671 SipeTLSCertificate *self = SIPE_TLS_CERTIFICATE(certificate);
673 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::accept");
675 if (self->state != SIPE_TLS_CERTIFICATE_PENDING) {
676 GError error = {
677 TP_ERROR,
678 TP_ERROR_INVALID_ARGUMENT,
679 "Calling Accept() on a certificate with state != PENDING "
680 "doesn't make sense."
683 dbus_g_method_return_error(context, &error);
684 return;
687 self->state = SIPE_TLS_CERTIFICATE_ACCEPTED;
688 tp_svc_authentication_tls_certificate_emit_accepted(self);
690 tp_svc_authentication_tls_certificate_return_from_accept(context);
693 static void tls_certificate_reject(TpSvcAuthenticationTLSCertificate *certificate,
694 const GPtrArray *rejections,
695 DBusGMethodInvocation *context)
697 SipeTLSCertificate *self = SIPE_TLS_CERTIFICATE(certificate);
699 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::reject");
701 if (self->state != SIPE_TLS_CERTIFICATE_PENDING) {
702 GError error = {
703 TP_ERROR,
704 TP_ERROR_INVALID_ARGUMENT,
705 "Calling Reject() on a certificate with state != PENDING "
706 "doesn't make sense."
709 dbus_g_method_return_error(context, &error);
710 return;
713 self->state = SIPE_TLS_CERTIFICATE_REJECTED;
715 tp_svc_authentication_tls_certificate_emit_rejected(self, rejections);
717 tp_svc_authentication_tls_certificate_return_from_reject(context);
720 static void tls_certificate_iface_init(gpointer g_iface,
721 SIPE_UNUSED_PARAMETER gpointer iface_data)
723 TpSvcAuthenticationTLSCertificateClass *klass = g_iface;
725 #define IMPLEMENT(x) \
726 tp_svc_authentication_tls_certificate_implement_##x( \
727 klass, tls_certificate_##x)
728 IMPLEMENT(accept);
729 IMPLEMENT(reject);
730 #undef IMPLEMENT
733 static void append_certificate_der(GPtrArray *certificates,
734 GByteArray *der)
736 GArray *array = g_array_sized_new(FALSE,
737 FALSE,
738 sizeof(guchar),
739 der->len);
740 array = g_array_append_vals(array, der->data, der->len);
741 g_byte_array_unref(der);
743 g_ptr_array_add(certificates, array);
746 struct sipe_tls_info *sipe_telepathy_tls_info_new(const gchar *hostname,
747 GTlsCertificate *certificate)
749 struct sipe_tls_info *tls_info = NULL;
750 GByteArray *der = NULL;
752 g_object_get(certificate, "certificate", &der, NULL);
753 if (der) {
754 GPtrArray *identities = g_ptr_array_new();
756 tls_info = g_new0(struct sipe_tls_info, 1);
757 tls_info->hostname = g_strdup(hostname);
759 /* build GStrv of identies */
760 g_ptr_array_add(identities, g_strdup(hostname));
761 g_ptr_array_add(identities, NULL);
762 tls_info->reference_identities = (GStrv) g_ptr_array_free(identities,
763 FALSE);
765 tls_info->cert_data = g_ptr_array_new_full(1,
766 (GDestroyNotify) g_array_unref);
767 /* unrefs "der" */
768 append_certificate_der(tls_info->cert_data, der);
770 /* will be unref'd in loop */
771 g_object_ref(certificate);
772 while (certificate) {
773 GTlsCertificate *issuer = NULL;
775 g_object_get(certificate, "issuer", &issuer, NULL);
776 g_object_unref(certificate);
778 /* add issuer certificate */
779 if (issuer) {
780 g_object_get(certificate, "certificate", &der, NULL);
781 /* unrefs "der" */
782 if (der)
783 append_certificate_der(tls_info->cert_data, der);
786 /* walk up the chain */
787 certificate = issuer;
791 return(tls_info);
794 void sipe_telepathy_tls_info_free(struct sipe_tls_info *tls_info)
796 g_object_unref(tls_info->certificate);
797 g_free(tls_info->hostname);
798 g_free(tls_info->cert_path);
799 g_ptr_array_unref(tls_info->cert_data);
800 g_strfreev(tls_info->reference_identities);
801 g_free(tls_info);
804 /* create new tls certificate object */
805 void sipe_telepathy_tls_verify_async(GObject *connection,
806 struct sipe_tls_info *tls_info,
807 GAsyncReadyCallback callback,
808 gpointer user_data)
810 /* property "connection" required by TpBaseChannel */
811 SipeTLSChannel *channel = g_object_new(SIPE_TYPE_TLS_CHANNEL,
812 "connection", connection,
813 NULL);
814 TpBaseChannel *base = TP_BASE_CHANNEL(channel);
815 SipeTLSCertificate *certificate = g_object_new(SIPE_TYPE_TLS_CERTIFICATE,
816 NULL);
817 TpDBusDaemon *daemon = tp_dbus_daemon_dup(NULL);
819 tls_info->certificate = certificate;
820 certificate->tls_info = tls_info;
822 tp_base_channel_register(base);
823 tls_info->cert_path = g_strdup_printf("%s/TLSCertificateObject",
824 tp_base_channel_get_object_path(base));
826 /* register the certificate on the bus */
827 tp_dbus_daemon_register_object(daemon,
828 tls_info->cert_path,
829 certificate);
830 g_object_unref(daemon);
832 channel_new_certificate(connection,
833 tls_info,
834 channel,
835 callback,
836 user_data);
840 Local Variables:
841 mode: c
842 c-file-style: "bsd"
843 indent-tabs-mode: t
844 tab-width: 8
845 End: