2 * @file telepathy-tls.c
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
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
{
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
55 * TLS Manager class - data structures
57 typedef struct _SipeTLSManagerClass
{
58 GObjectClass parent_class
;
59 } SipeTLSManagerClass
;
61 typedef struct _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, \
80 * TLS Channel class - data structures
82 typedef struct _SipeTLSChannelClass
{
83 TpBaseChannelClass parent_class
;
84 } SipeTLSChannelClass
;
86 typedef struct _SipeTLSChannel
{
89 const struct sipe_tls_info
*tls_info
;
91 GSimpleAsyncResult
*result
;
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, \
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
{
116 const struct sipe_tls_info
*tls_info
;
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, \
133 * TLS Manager class - type definition
135 static void channel_manager_iface_init(gpointer
, gpointer
);
136 G_DEFINE_TYPE_WITH_CODE(SipeTLSManager
,
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
,
148 TP_TYPE_BASE_CHANNEL
,
149 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CHANNEL_TYPE_SERVER_TLS_CONNECTION
,
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
,
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
;
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
);
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
;
199 GSList
*next
= entry
->next
;
200 /* removes entry from list */
201 tp_base_channel_close(entry
->data
);
205 tp_clear_object(&self
->connection
);
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
236 static void foreach_channel(TpChannelManager
*manager
,
237 TpExportableChannelFunc func
,
240 SipeTLSManager
*self
= SIPE_TLS_MANAGER(manager
);
242 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSManager::foreach_channel");
250 static void channel_manager_iface_init(gpointer g_iface
,
251 SIPE_UNUSED_PARAMETER gpointer iface_data
)
253 TpChannelManagerIface
*iface
= g_iface
;
255 #define IMPLEMENT(x, y) iface->x = y
256 IMPLEMENT(foreach_channel
, foreach_channel
);
257 /* These channels are not requestable. */
258 IMPLEMENT(type_foreach_channel_class
, NULL
);
259 IMPLEMENT(create_channel
, NULL
);
260 IMPLEMENT(request_channel
, NULL
);
261 IMPLEMENT(ensure_channel
, NULL
);
265 /* create new TLS manager object */
266 SipeTLSManager
*sipe_telepathy_tls_new(TpBaseConnection
*connection
)
268 SipeTLSManager
*self
= g_object_new(SIPE_TYPE_TLS_MANAGER
, NULL
);
269 self
->connection
= g_object_ref(connection
);
273 static void channel_closed_cb(SipeTLSChannel
*channel
,
274 SipeTLSManager
*self
)
276 self
->channels
= g_slist_remove(self
->channels
, channel
);
277 tp_channel_manager_emit_channel_closed_for_object(self
,
278 TP_EXPORTABLE_CHANNEL(channel
));
279 g_object_unref(channel
);
282 static void manager_new_channel(SipeTLSManager
*self
,
283 SipeTLSChannel
*channel
)
285 self
->channels
= g_slist_prepend(self
->channels
,
286 g_object_ref(channel
));
288 g_signal_connect(channel
,
290 G_CALLBACK(channel_closed_cb
),
293 /* emit NewChannel on the ChannelManager iface */
294 tp_channel_manager_emit_new_channel(self
,
295 TP_EXPORTABLE_CHANNEL(channel
),
301 * TLS Channel class - instance methods
304 CHANNEL_PROP_SERVER_CERTIFICATE
= 1,
305 CHANNEL_PROP_HOSTNAME
,
306 CHANNEL_PROP_REFERENCE_IDENTITIES
,
310 static void channel_get_property(GObject
*object
,
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
);
321 case CHANNEL_PROP_HOSTNAME
:
322 g_value_set_string(value
, self
->tls_info
->hostname
);
324 case CHANNEL_PROP_REFERENCE_IDENTITIES
:
325 g_value_set_boxed(value
, self
->tls_info
->reference_identities
);
328 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, property_id
, pspec
);
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
,
338 tp_dbus_properties_mixin_fill_properties_hash(G_OBJECT(channel
),
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",
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 SipeTLSChannel
*self
= SIPE_TLS_CHANNEL(object
);
354 void (*chain_up
)(GObject
*) = G_OBJECT_CLASS(sipe_tls_channel_parent_class
)->constructed
;
363 static void sipe_tls_channel_finalize(GObject
*object
)
365 SipeTLSChannel
*self
= SIPE_TLS_CHANNEL(object
);
367 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::finalize");
369 g_simple_async_result_complete(self
->result
);
370 g_clear_object(&self
->result
);
372 G_OBJECT_CLASS(sipe_tls_channel_parent_class
)->finalize(object
);
376 * TLS Channel class - type implementation
378 static void sipe_tls_channel_class_init(SipeTLSChannelClass
*klass
)
380 static TpDBusPropertiesMixinPropImpl props
[] = {
382 .name
= "ServerCertificate",
383 .getter_data
= "server-certificate",
388 .getter_data
= "hostname",
392 .name
= "ReferenceIdentities",
393 .getter_data
= "reference-identities",
400 GObjectClass
*object_class
= G_OBJECT_CLASS(klass
);
401 TpBaseChannelClass
*base_class
= TP_BASE_CHANNEL_CLASS(klass
);
404 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::class_init");
406 object_class
->constructed
= sipe_tls_channel_constructed
;
407 object_class
->finalize
= sipe_tls_channel_finalize
;
408 object_class
->get_property
= channel_get_property
;
410 base_class
->channel_type
= TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION
;
411 base_class
->target_handle_type
= TP_HANDLE_TYPE_NONE
;
412 base_class
->fill_immutable_properties
= channel_fill_immutable_properties
;
413 base_class
->get_object_path_suffix
= channel_get_object_path_suffix
;
414 base_class
->interfaces
= NULL
;
415 base_class
->close
= tp_base_channel_destroyed
;
417 ps
= g_param_spec_boxed("server-certificate",
418 "Server certificate path",
419 "The object path of the server certificate.",
420 DBUS_TYPE_G_OBJECT_PATH
,
421 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
422 g_object_class_install_property(object_class
,
423 CHANNEL_PROP_SERVER_CERTIFICATE
,
426 ps
= g_param_spec_string("hostname",
427 "The hostname to be verified",
428 "The hostname which should be certified by the server certificate.",
430 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
431 g_object_class_install_property(object_class
,
432 CHANNEL_PROP_HOSTNAME
,
435 ps
= g_param_spec_boxed("reference-identities",
436 "The various identities to check the certificate against",
437 "The server certificate identity should match one of these identities.",
439 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
440 g_object_class_install_property(object_class
,
441 CHANNEL_PROP_REFERENCE_IDENTITIES
,
444 tp_dbus_properties_mixin_implement_interface(object_class
,
445 TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION
,
446 tp_dbus_properties_mixin_getter_gobject_properties
,
451 static void sipe_tls_channel_init(SIPE_UNUSED_PARAMETER SipeTLSChannel
*self
)
453 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::init");
457 * TLS Certificate class - instance methods
460 CERTIFICATE_PROP_OBJECT_PATH
= 1,
461 CERTIFICATE_PROP_STATE
,
462 CERTIFICATE_PROP_TYPE
,
463 CERTIFICATE_PROP_CHAIN_DATA
,
464 CERTIFICATE_LAST_PROP
467 static void certificate_get_property(GObject
*object
,
472 SipeTLSCertificate
*self
= SIPE_TLS_CERTIFICATE(object
);
474 switch (property_id
) {
475 case CERTIFICATE_PROP_OBJECT_PATH
:
476 g_value_set_string(value
, self
->tls_info
->cert_path
);
478 case CERTIFICATE_PROP_STATE
:
479 g_value_set_uint(value
, self
->state
);
481 case CERTIFICATE_PROP_TYPE
:
482 g_value_set_string(value
, "x509");
484 case CERTIFICATE_PROP_CHAIN_DATA
:
485 g_value_set_boxed(value
, self
->tls_info
->cert_data
);
488 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, property_id
, pspec
);
493 static void sipe_tls_certificate_constructed(GObject
*object
)
495 SipeTLSCertificate
*self
= SIPE_TLS_CERTIFICATE(object
);
496 void (*chain_up
)(GObject
*) = G_OBJECT_CLASS(sipe_tls_certificate_parent_class
)->constructed
;
501 self
->state
= SIPE_TLS_CERTIFICATE_PENDING
;
504 static void sipe_tls_certificate_finalize(GObject
*object
)
506 SipeTLSCertificate
*self
= SIPE_TLS_CERTIFICATE(object
);
508 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::finalize");
513 G_OBJECT_CLASS(sipe_tls_certificate_parent_class
)->finalize(object
);
517 * TLS Certificate class - type implementation
519 static void sipe_tls_certificate_class_init(SipeTLSCertificateClass
*klass
)
521 static TpDBusPropertiesMixinPropImpl props
[] = {
524 .getter_data
= "state",
528 .name
= "CertificateType",
529 .getter_data
= "certificate-type",
533 .name
= "CertificateChainData",
534 .getter_data
= "certificate-chain-data",
541 static TpDBusPropertiesMixinIfaceImpl prop_interfaces
[] = {
543 .name
= TP_IFACE_AUTHENTICATION_TLS_CERTIFICATE
,
544 .getter
= tp_dbus_properties_mixin_getter_gobject_properties
,
552 GObjectClass
*object_class
= G_OBJECT_CLASS(klass
);
555 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::class_init");
557 klass
->dbus_props_class
.interfaces
= prop_interfaces
;
559 object_class
->constructed
= sipe_tls_certificate_constructed
;
560 object_class
->finalize
= sipe_tls_certificate_finalize
;
561 object_class
->get_property
= certificate_get_property
;
563 ps
= g_param_spec_string("object-path",
565 "The D-Bus object path used for this object on the bus.",
567 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
568 g_object_class_install_property(object_class
,
569 CERTIFICATE_PROP_OBJECT_PATH
,
572 ps
= g_param_spec_uint("state",
573 "State of this certificate",
574 "The state of this TLS certificate.",
575 SIPE_TLS_CERTIFICATE_PENDING
,
576 SIPE_TLS_CERTIFICATE_ACCEPTED
,
577 SIPE_TLS_CERTIFICATE_PENDING
,
578 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
579 g_object_class_install_property(object_class
,
580 CERTIFICATE_PROP_STATE
,
583 ps
= g_param_spec_string("certificate-type",
584 "The certificate type",
585 "The type of this certificate.",
587 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
588 g_object_class_install_property(object_class
,
589 CERTIFICATE_PROP_TYPE
,
592 ps
= g_param_spec_boxed("certificate-chain-data",
593 "The certificate chain data",
594 "The raw PEM-encoded trust chain of this certificate.",
595 TP_ARRAY_TYPE_UCHAR_ARRAY_LIST
,
596 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
597 g_object_class_install_property(object_class
,
598 CERTIFICATE_PROP_CHAIN_DATA
, ps
);
600 tp_dbus_properties_mixin_class_init(object_class
,
601 G_STRUCT_OFFSET(SipeTLSCertificateClass
, dbus_props_class
));
604 static void sipe_tls_certificate_init(SIPE_UNUSED_PARAMETER SipeTLSCertificate
*self
)
606 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::init");
610 * TLS Certificate class - interface implementation
612 static void tls_certificate_accept(TpSvcAuthenticationTLSCertificate
*certificate
,
613 DBusGMethodInvocation
*context
)
615 SipeTLSCertificate
*self
= SIPE_TLS_CERTIFICATE(certificate
);
617 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::accept");
619 if (self
->state
!= SIPE_TLS_CERTIFICATE_PENDING
) {
622 TP_ERROR_INVALID_ARGUMENT
,
623 "Calling Accept() on a certificate with state != PENDING "
624 "doesn't make sense."
627 dbus_g_method_return_error(context
, &error
);
631 self
->state
= SIPE_TLS_CERTIFICATE_ACCEPTED
;
632 tp_svc_authentication_tls_certificate_emit_accepted(self
);
634 tp_svc_authentication_tls_certificate_return_from_accept(context
);
637 static void tls_certificate_reject(TpSvcAuthenticationTLSCertificate
*certificate
,
638 const GPtrArray
*rejections
,
639 DBusGMethodInvocation
*context
)
641 SipeTLSCertificate
*self
= SIPE_TLS_CERTIFICATE(certificate
);
643 SIPE_DEBUG_INFO_NOFORMAT("SipeTLSCertificate::reject");
645 if (self
->state
!= SIPE_TLS_CERTIFICATE_PENDING
) {
648 TP_ERROR_INVALID_ARGUMENT
,
649 "Calling Reject() on a certificate with state != PENDING "
650 "doesn't make sense."
653 dbus_g_method_return_error(context
, &error
);
657 self
->state
= SIPE_TLS_CERTIFICATE_REJECTED
;
659 tp_svc_authentication_tls_certificate_emit_rejected(self
, rejections
);
661 tp_svc_authentication_tls_certificate_return_from_reject(context
);
664 static void tls_certificate_iface_init(gpointer g_iface
,
665 SIPE_UNUSED_PARAMETER gpointer iface_data
)
667 TpSvcAuthenticationTLSCertificateClass
*klass
= g_iface
;
669 #define IMPLEMENT(x) \
670 tp_svc_authentication_tls_certificate_implement_##x( \
671 klass, tls_certificate_##x)
677 struct sipe_tls_info
*sipe_telepathy_tls_info_new(const gchar
*hostname
,
678 GTlsCertificate
*certificate
)
680 struct sipe_tls_info
*tls_info
= NULL
;
683 g_object_get(certificate
, "certificate-pem", &pem
, NULL
);
685 guint length
= strlen(pem
);
686 GArray
*array
= g_array_sized_new(TRUE
,
691 SIPE_DEBUG_INFO("sipe_telepathy_tls_info_new: '%s' (%d)", pem
, length
);
693 tls_info
= g_new0(struct sipe_tls_info
, 1);
694 tls_info
->hostname
= g_strdup(hostname
);
695 tls_info
->reference_identities
= g_strsplit("", "", 0);
697 array
= g_array_append_vals(array
, pem
, length
);
700 tls_info
->cert_data
= g_ptr_array_new_full(1, (GDestroyNotify
) g_array_unref
);
701 g_ptr_array_add(tls_info
->cert_data
, array
);
707 void sipe_telepathy_tls_info_free(struct sipe_tls_info
*tls_info
)
709 g_object_unref(tls_info
->certificate
);
710 g_free(tls_info
->hostname
);
711 g_free(tls_info
->cert_path
);
712 g_ptr_array_unref(tls_info
->cert_data
);
713 g_strfreev(tls_info
->reference_identities
);
717 /* create new tls certificate object */
718 void sipe_telepathy_tls_verify_async(GObject
*connection
,
719 struct sipe_tls_info
*tls_info
,
720 GAsyncReadyCallback callback
,
723 struct sipe_backend_private
*telepathy_private
= sipe_telepathy_connection_private(connection
);
724 /* property "connection" required by TpBaseChannel */
725 SipeTLSChannel
*channel
= g_object_new(SIPE_TYPE_TLS_CHANNEL
,
726 "connection", connection
,
728 TpBaseChannel
*base
= TP_BASE_CHANNEL(channel
);
729 SipeTLSCertificate
*certificate
= g_object_new(SIPE_TYPE_TLS_CERTIFICATE
,
731 TpDBusDaemon
*daemon
= tp_dbus_daemon_dup(NULL
);
733 tls_info
->certificate
= certificate
;
734 channel
->tls_info
= tls_info
;
735 certificate
->tls_info
= tls_info
;
737 tp_base_channel_register(base
);
738 tls_info
->cert_path
= g_strdup_printf("%s/TLSCertificateObject",
739 tp_base_channel_get_object_path(base
));
741 /* register the certificate on the bus */
742 tp_dbus_daemon_register_object(daemon
,
745 g_object_unref(daemon
);
747 channel
->result
= g_simple_async_result_new(G_OBJECT(channel
),
750 sipe_telepathy_tls_verify_async
);
752 manager_new_channel(telepathy_private
->tls_manager
, channel
);