Copy TLS channel code from gabble
Take the TLS channel handling code from Gabble and s/gabble/idle in
the various files, but no other changes
Sjoerd Simons
11 years ago
0 | /* | |
1 | * server-tls-channel.c - Source for IdleServerTLSChannel | |
2 | * Copyright (C) 2010 Collabora Ltd. | |
3 | * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> | |
4 | * | |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2.1 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this library; if not, write to the Free Software | |
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | */ | |
19 | ||
20 | #include <config.h> | |
21 | ||
22 | #include "server-tls-channel.h" | |
23 | ||
24 | #include <telepathy-glib/telepathy-glib.h> | |
25 | #include <telepathy-glib/telepathy-glib-dbus.h> | |
26 | ||
27 | #include <wocky/wocky.h> | |
28 | ||
29 | #define DEBUG_FLAG IDLE_DEBUG_TLS | |
30 | #include "debug.h" | |
31 | #include "connection.h" | |
32 | #include "tls-certificate.h" | |
33 | ||
34 | G_DEFINE_TYPE_WITH_CODE (IdleServerTLSChannel, idle_server_tls_channel, | |
35 | TP_TYPE_BASE_CHANNEL, | |
36 | G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_SERVER_TLS_CONNECTION, | |
37 | NULL)); | |
38 | ||
39 | static void idle_server_tls_channel_close (TpBaseChannel *base); | |
40 | ||
41 | enum { | |
42 | /* server TLS channel iface */ | |
43 | PROP_SERVER_CERTIFICATE = 1, | |
44 | PROP_HOSTNAME, | |
45 | PROP_REFERENCE_IDENTITIES, | |
46 | ||
47 | /* not exported */ | |
48 | PROP_TLS_SESSION, | |
49 | ||
50 | NUM_PROPERTIES | |
51 | }; | |
52 | ||
53 | struct _IdleServerTLSChannelPrivate { | |
54 | WockyTLSSession *tls_session; | |
55 | ||
56 | IdleTLSCertificate *server_cert; | |
57 | gchar *server_cert_path; | |
58 | gchar *hostname; | |
59 | GStrv reference_identities; | |
60 | ||
61 | gboolean dispose_has_run; | |
62 | }; | |
63 | ||
64 | static void | |
65 | idle_server_tls_channel_get_property (GObject *object, | |
66 | guint property_id, | |
67 | GValue *value, | |
68 | GParamSpec *pspec) | |
69 | { | |
70 | IdleServerTLSChannel *self = IDLE_SERVER_TLS_CHANNEL (object); | |
71 | ||
72 | switch (property_id) | |
73 | { | |
74 | case PROP_SERVER_CERTIFICATE: | |
75 | g_value_set_boxed (value, self->priv->server_cert_path); | |
76 | break; | |
77 | case PROP_HOSTNAME: | |
78 | g_value_set_string (value, self->priv->hostname); | |
79 | break; | |
80 | case PROP_REFERENCE_IDENTITIES: | |
81 | g_value_set_boxed (value, self->priv->reference_identities); | |
82 | break; | |
83 | case PROP_TLS_SESSION: | |
84 | g_value_set_object (value, self->priv->tls_session); | |
85 | break; | |
86 | default: | |
87 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | |
88 | break; | |
89 | } | |
90 | } | |
91 | ||
92 | static void | |
93 | idle_server_tls_channel_set_property (GObject *object, | |
94 | guint property_id, | |
95 | const GValue *value, | |
96 | GParamSpec *pspec) | |
97 | { | |
98 | IdleServerTLSChannel *self = IDLE_SERVER_TLS_CHANNEL (object); | |
99 | ||
100 | switch (property_id) | |
101 | { | |
102 | case PROP_TLS_SESSION: | |
103 | self->priv->tls_session = g_value_dup_object (value); | |
104 | break; | |
105 | case PROP_HOSTNAME: | |
106 | self->priv->hostname = g_value_dup_string (value); | |
107 | break; | |
108 | case PROP_REFERENCE_IDENTITIES: | |
109 | self->priv->reference_identities = g_value_dup_boxed (value); | |
110 | break; | |
111 | default: | |
112 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | |
113 | break; | |
114 | } | |
115 | } | |
116 | ||
117 | static void | |
118 | idle_server_tls_channel_finalize (GObject *object) | |
119 | { | |
120 | IdleServerTLSChannel *self = IDLE_SERVER_TLS_CHANNEL (object); | |
121 | ||
122 | DEBUG ("Finalize TLS channel"); | |
123 | ||
124 | g_free (self->priv->server_cert_path); | |
125 | g_free (self->priv->hostname); | |
126 | g_strfreev (self->priv->reference_identities); | |
127 | ||
128 | G_OBJECT_CLASS (idle_server_tls_channel_parent_class)->finalize (object); | |
129 | } | |
130 | ||
131 | static void | |
132 | idle_server_tls_channel_dispose (GObject *object) | |
133 | { | |
134 | IdleServerTLSChannel *self = IDLE_SERVER_TLS_CHANNEL (object); | |
135 | ||
136 | if (self->priv->dispose_has_run) | |
137 | return; | |
138 | ||
139 | DEBUG ("Dispose TLS channel"); | |
140 | ||
141 | self->priv->dispose_has_run = TRUE; | |
142 | ||
143 | tp_clear_object (&self->priv->server_cert); | |
144 | tp_clear_object (&self->priv->tls_session); | |
145 | ||
146 | G_OBJECT_CLASS (idle_server_tls_channel_parent_class)->dispose (object); | |
147 | } | |
148 | ||
149 | static const gchar * | |
150 | cert_type_to_str (WockyTLSCertType type) | |
151 | { | |
152 | const gchar *retval = NULL; | |
153 | ||
154 | switch (type) | |
155 | { | |
156 | case WOCKY_TLS_CERT_TYPE_X509: | |
157 | retval = "x509"; | |
158 | break; | |
159 | case WOCKY_TLS_CERT_TYPE_OPENPGP: | |
160 | retval = "pgp"; | |
161 | break; | |
162 | default: | |
163 | break; | |
164 | } | |
165 | ||
166 | return retval; | |
167 | } | |
168 | ||
169 | static void | |
170 | idle_server_tls_channel_constructed (GObject *object) | |
171 | { | |
172 | IdleServerTLSChannel *self = IDLE_SERVER_TLS_CHANNEL (object); | |
173 | TpBaseChannel *base = TP_BASE_CHANNEL (self); | |
174 | TpBaseConnection *base_conn = tp_base_channel_get_connection (base); | |
175 | void (*chain_up) (GObject *) = | |
176 | G_OBJECT_CLASS (idle_server_tls_channel_parent_class)->constructed; | |
177 | WockyTLSCertType cert_type; | |
178 | const gchar *path; | |
179 | gchar *cert_object_path; | |
180 | GPtrArray *certificates; | |
181 | ||
182 | if (chain_up != NULL) | |
183 | chain_up (object); | |
184 | ||
185 | tp_base_channel_register (base); | |
186 | ||
187 | /* create the TLS certificate object */ | |
188 | path = tp_base_channel_get_object_path (base); | |
189 | cert_object_path = g_strdup_printf ("%s/TLSCertificateObject", path); | |
190 | certificates = wocky_tls_session_get_peers_certificate ( | |
191 | self->priv->tls_session, &cert_type); | |
192 | ||
193 | self->priv->server_cert = g_object_new (IDLE_TYPE_TLS_CERTIFICATE, | |
194 | "object-path", cert_object_path, | |
195 | "certificate-chain-data", certificates, | |
196 | "certificate-type", cert_type_to_str (cert_type), | |
197 | "dbus-daemon", IDLE_CONNECTION (base_conn)->daemon, | |
198 | NULL); | |
199 | self->priv->server_cert_path = cert_object_path; | |
200 | ||
201 | DEBUG ("Server TLS channel constructed at %s", path); | |
202 | } | |
203 | ||
204 | static void | |
205 | idle_server_tls_channel_fill_immutable_properties ( | |
206 | TpBaseChannel *chan, | |
207 | GHashTable *properties) | |
208 | { | |
209 | TP_BASE_CHANNEL_CLASS (idle_server_tls_channel_parent_class) | |
210 | ->fill_immutable_properties (chan, properties); | |
211 | ||
212 | tp_dbus_properties_mixin_fill_properties_hash ( | |
213 | G_OBJECT (chan), properties, | |
214 | TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ServerCertificate", | |
215 | TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "Hostname", | |
216 | TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ReferenceIdentities", | |
217 | NULL); | |
218 | } | |
219 | ||
220 | static gchar * | |
221 | idle_server_tls_channel_get_object_path_suffix (TpBaseChannel *base) | |
222 | { | |
223 | static guint count = 0; | |
224 | ||
225 | return g_strdup_printf ("ServerTLSChannel%u", ++count); | |
226 | } | |
227 | ||
228 | static void | |
229 | idle_server_tls_channel_init (IdleServerTLSChannel *self) | |
230 | { | |
231 | self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, | |
232 | IDLE_TYPE_SERVER_TLS_CHANNEL, IdleServerTLSChannelPrivate); | |
233 | } | |
234 | ||
235 | static void | |
236 | idle_server_tls_channel_class_init (IdleServerTLSChannelClass *klass) | |
237 | { | |
238 | static TpDBusPropertiesMixinPropImpl server_tls_props[] = { | |
239 | { "ServerCertificate", "server-certificate", NULL }, | |
240 | { "Hostname", "hostname", NULL }, | |
241 | { "ReferenceIdentities", "reference-identities", NULL }, | |
242 | { NULL } | |
243 | }; | |
244 | ||
245 | GObjectClass *oclass = G_OBJECT_CLASS (klass); | |
246 | TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); | |
247 | GParamSpec *pspec; | |
248 | ||
249 | g_type_class_add_private (klass, sizeof (IdleServerTLSChannelPrivate)); | |
250 | ||
251 | oclass->get_property = idle_server_tls_channel_get_property; | |
252 | oclass->set_property = idle_server_tls_channel_set_property; | |
253 | oclass->dispose = idle_server_tls_channel_dispose; | |
254 | oclass->finalize = idle_server_tls_channel_finalize; | |
255 | oclass->constructed = idle_server_tls_channel_constructed; | |
256 | ||
257 | base_class->channel_type = TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION; | |
258 | base_class->target_handle_type = TP_HANDLE_TYPE_NONE; | |
259 | base_class->fill_immutable_properties = | |
260 | idle_server_tls_channel_fill_immutable_properties; | |
261 | base_class->get_object_path_suffix = | |
262 | idle_server_tls_channel_get_object_path_suffix; | |
263 | base_class->close = idle_server_tls_channel_close; | |
264 | ||
265 | pspec = g_param_spec_boxed ("server-certificate", "Server certificate path", | |
266 | "The object path of the server certificate.", | |
267 | DBUS_TYPE_G_OBJECT_PATH, | |
268 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); | |
269 | g_object_class_install_property (oclass, PROP_SERVER_CERTIFICATE, pspec); | |
270 | ||
271 | pspec = g_param_spec_string ("hostname", "The hostname to be verified", | |
272 | "The hostname which should be certified by the server certificate.", | |
273 | NULL, | |
274 | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); | |
275 | g_object_class_install_property (oclass, PROP_HOSTNAME, pspec); | |
276 | ||
277 | pspec = g_param_spec_boxed ("reference-identities", | |
278 | "The various identities to check the certificate against", | |
279 | "The server certificate identity should match one of these identities.", | |
280 | G_TYPE_STRV, | |
281 | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); | |
282 | g_object_class_install_property (oclass, PROP_REFERENCE_IDENTITIES, pspec); | |
283 | ||
284 | pspec = g_param_spec_object ("tls-session", "The WockyTLSSession", | |
285 | "The WockyTLSSession object containing the TLS information", | |
286 | WOCKY_TYPE_TLS_SESSION, | |
287 | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); | |
288 | g_object_class_install_property (oclass, PROP_TLS_SESSION, pspec); | |
289 | ||
290 | tp_dbus_properties_mixin_implement_interface (oclass, | |
291 | TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION, | |
292 | tp_dbus_properties_mixin_getter_gobject_properties, NULL, | |
293 | server_tls_props); | |
294 | } | |
295 | ||
296 | static void | |
297 | idle_server_tls_channel_close (TpBaseChannel *base) | |
298 | { | |
299 | DEBUG ("Close() called on the TLS channel %p", base); | |
300 | tp_base_channel_destroyed (base); | |
301 | } | |
302 | ||
303 | IdleTLSCertificate * | |
304 | idle_server_tls_channel_get_certificate (IdleServerTLSChannel *self) | |
305 | { | |
306 | return self->priv->server_cert; | |
307 | } |
0 | /* | |
1 | * server-tls-channel.h - Header for IdleServerTLSChannel | |
2 | * Copyright (C) 2010 Collabora Ltd. | |
3 | * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> | |
4 | * | |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2.1 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this library; if not, write to the Free Software | |
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | */ | |
19 | ||
20 | #ifndef __IDLE_SERVER_TLS_CHANNEL_H__ | |
21 | #define __IDLE_SERVER_TLS_CHANNEL_H__ | |
22 | ||
23 | #include <glib-object.h> | |
24 | ||
25 | #include <telepathy-glib/telepathy-glib.h> | |
26 | ||
27 | #include <extensions/extensions.h> | |
28 | ||
29 | #include "tls-certificate.h" | |
30 | ||
31 | G_BEGIN_DECLS | |
32 | ||
33 | typedef struct _IdleServerTLSChannelPrivate IdleServerTLSChannelPrivate; | |
34 | typedef struct _IdleServerTLSChannelClass IdleServerTLSChannelClass; | |
35 | typedef struct _IdleServerTLSChannel IdleServerTLSChannel; | |
36 | ||
37 | struct _IdleServerTLSChannelClass { | |
38 | TpBaseChannelClass base_class; | |
39 | }; | |
40 | ||
41 | struct _IdleServerTLSChannel { | |
42 | TpBaseChannel parent; | |
43 | ||
44 | IdleServerTLSChannelPrivate *priv; | |
45 | }; | |
46 | ||
47 | GType idle_server_tls_channel_get_type (void); | |
48 | ||
49 | #define IDLE_TYPE_SERVER_TLS_CHANNEL \ | |
50 | (idle_server_tls_channel_get_type ()) | |
51 | #define IDLE_SERVER_TLS_CHANNEL(obj) \ | |
52 | (G_TYPE_CHECK_INSTANCE_CAST((obj), IDLE_TYPE_SERVER_TLS_CHANNEL, \ | |
53 | IdleServerTLSChannel)) | |
54 | #define IDLE_SERVER_TLS_CHANNEL_CLASS(klass) \ | |
55 | (G_TYPE_CHECK_CLASS_CAST((klass), IDLE_TYPE_SERVER_TLS_CHANNEL, \ | |
56 | IdleServerTLSChannelClass)) | |
57 | #define IDLE_IS_SERVER_TLS_CHANNEL(obj) \ | |
58 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), IDLE_TYPE_SERVER_TLS_CHANNEL)) | |
59 | #define IDLE_IS_SERVER_TLS_CHANNEL_CLASS(klass) \ | |
60 | (G_TYPE_CHECK_CLASS_TYPE((klass), IDLE_TYPE_SERVER_TLS_CHANNEL)) | |
61 | #define IDLE_SERVER_TLS_CHANNEL_GET_CLASS(obj) \ | |
62 | (G_TYPE_INSTANCE_GET_CLASS ((obj), IDLE_TYPE_SERVER_TLS_CHANNEL,\ | |
63 | IdleServerTLSChannelClass)) | |
64 | ||
65 | IdleTLSCertificate * idle_server_tls_channel_get_certificate ( | |
66 | IdleServerTLSChannel *self); | |
67 | ||
68 | G_END_DECLS | |
69 | ||
70 | #endif /* #ifndef __IDLE_SERVER_TLS_CHANNEL_H__*/ |
0 | /* | |
1 | * server-tls-manager.c - Source for IdleServerTLSManager | |
2 | * Copyright (C) 2010 Collabora Ltd. | |
3 | * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> | |
4 | * | |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2.1 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this library; if not, write to the Free Software | |
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | */ | |
19 | ||
20 | #include "config.h" | |
21 | #include "server-tls-manager.h" | |
22 | ||
23 | #include <telepathy-glib/telepathy-glib.h> | |
24 | #include <telepathy-glib/telepathy-glib-dbus.h> | |
25 | ||
26 | #define DEBUG_FLAG IDLE_DEBUG_TLS | |
27 | #include "debug.h" | |
28 | #include "gabble/caps-channel-manager.h" | |
29 | #include "connection.h" | |
30 | #include "server-tls-channel.h" | |
31 | #include "util.h" | |
32 | ||
33 | #include "extensions/extensions.h" | |
34 | ||
35 | #include <wocky/wocky.h> | |
36 | ||
37 | static void channel_manager_iface_init (gpointer, gpointer); | |
38 | ||
39 | G_DEFINE_TYPE_WITH_CODE (IdleServerTLSManager, idle_server_tls_manager, | |
40 | WOCKY_TYPE_TLS_HANDLER, | |
41 | G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, | |
42 | channel_manager_iface_init); | |
43 | G_IMPLEMENT_INTERFACE (IDLE_TYPE_CAPS_CHANNEL_MANAGER, | |
44 | NULL)); | |
45 | ||
46 | enum { | |
47 | PROP_CONNECTION = 1, | |
48 | PROP_INTERACTIVE_TLS, | |
49 | NUM_PROPERTIES | |
50 | }; | |
51 | ||
52 | struct _IdleServerTLSManagerPrivate { | |
53 | /* Properties */ | |
54 | IdleConnection *connection; | |
55 | gboolean interactive_tls; | |
56 | ||
57 | /* Current operation data */ | |
58 | gchar *peername; | |
59 | GStrv reference_identities; | |
60 | WockyTLSSession *tls_session; | |
61 | IdleServerTLSChannel *channel; | |
62 | GSimpleAsyncResult *async_result; | |
63 | ||
64 | /* List of owned TpBaseChannel not yet closed by the client */ | |
65 | GList *completed_channels; | |
66 | ||
67 | gboolean dispose_has_run; | |
68 | }; | |
69 | ||
70 | #define chainup ((WockyTLSHandlerClass *) \ | |
71 | idle_server_tls_manager_parent_class) | |
72 | ||
73 | static void | |
74 | idle_server_tls_manager_get_property (GObject *object, | |
75 | guint property_id, | |
76 | GValue *value, | |
77 | GParamSpec *pspec) | |
78 | { | |
79 | IdleServerTLSManager *self = IDLE_SERVER_TLS_MANAGER (object); | |
80 | ||
81 | switch (property_id) | |
82 | { | |
83 | case PROP_CONNECTION: | |
84 | g_value_set_object (value, self->priv->connection); | |
85 | break; | |
86 | case PROP_INTERACTIVE_TLS: | |
87 | g_value_set_boolean (value, self->priv->interactive_tls); | |
88 | break; | |
89 | default: | |
90 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | |
91 | break; | |
92 | } | |
93 | } | |
94 | ||
95 | static void | |
96 | idle_server_tls_manager_set_property (GObject *object, | |
97 | guint property_id, | |
98 | const GValue *value, | |
99 | GParamSpec *pspec) | |
100 | { | |
101 | IdleServerTLSManager *self = IDLE_SERVER_TLS_MANAGER (object); | |
102 | ||
103 | switch (property_id) | |
104 | { | |
105 | case PROP_CONNECTION: | |
106 | self->priv->connection = g_value_dup_object (value); | |
107 | break; | |
108 | case PROP_INTERACTIVE_TLS: | |
109 | self->priv->interactive_tls = g_value_get_boolean (value); | |
110 | break; | |
111 | default: | |
112 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | |
113 | break; | |
114 | } | |
115 | } | |
116 | ||
117 | static void | |
118 | close_all (IdleServerTLSManager *self) | |
119 | { | |
120 | GList *l; | |
121 | ||
122 | if (self->priv->channel != NULL) | |
123 | tp_base_channel_close (TP_BASE_CHANNEL (self->priv->channel)); | |
124 | ||
125 | l = self->priv->completed_channels; | |
126 | while (l != NULL) | |
127 | { | |
128 | /* use a temporary variable as the ::closed callback will delete | |
129 | * the link from the list. */ | |
130 | GList *next = l->next; | |
131 | ||
132 | tp_base_channel_close (l->data); | |
133 | ||
134 | l = next; | |
135 | } | |
136 | } | |
137 | ||
138 | static void | |
139 | connection_status_changed_cb (IdleConnection *conn, | |
140 | guint status, | |
141 | guint reason, | |
142 | gpointer user_data) | |
143 | { | |
144 | IdleServerTLSManager *self = user_data; | |
145 | ||
146 | DEBUG ("Connection status changed, now %d", status); | |
147 | ||
148 | if (status == TP_CONNECTION_STATUS_DISCONNECTED) | |
149 | { | |
150 | close_all (self); | |
151 | tp_clear_object (&self->priv->connection); | |
152 | } | |
153 | } | |
154 | ||
155 | static void | |
156 | complete_verify (IdleServerTLSManager *self) | |
157 | { | |
158 | /* Move channel to a list until a client Close() it */ | |
159 | if (self->priv->channel != NULL) | |
160 | { | |
161 | self->priv->completed_channels = g_list_prepend ( | |
162 | self->priv->completed_channels, | |
163 | g_object_ref (self->priv->channel)); | |
164 | } | |
165 | ||
166 | g_simple_async_result_complete (self->priv->async_result); | |
167 | ||
168 | /* Reset to initial state */ | |
169 | tp_clear_pointer (&self->priv->peername, g_free); | |
170 | tp_clear_pointer (&self->priv->reference_identities, g_strfreev); | |
171 | g_clear_object (&self->priv->tls_session); | |
172 | g_clear_object (&self->priv->channel); | |
173 | g_clear_object (&self->priv->async_result); | |
174 | } | |
175 | ||
176 | static void | |
177 | verify_fallback_cb (GObject *source, | |
178 | GAsyncResult *result, | |
179 | gpointer user_data) | |
180 | { | |
181 | IdleServerTLSManager *self = (IdleServerTLSManager *) source; | |
182 | GError *error = NULL; | |
183 | ||
184 | if (!chainup->verify_finish_func (WOCKY_TLS_HANDLER (self), result, &error)) | |
185 | g_simple_async_result_take_error (self->priv->async_result, error); | |
186 | ||
187 | complete_verify (self); | |
188 | } | |
189 | ||
190 | static void | |
191 | server_tls_channel_closed_cb (IdleServerTLSChannel *channel, | |
192 | gpointer user_data) | |
193 | { | |
194 | IdleServerTLSManager *self = user_data; | |
195 | ||
196 | DEBUG ("Server TLS channel closed."); | |
197 | ||
198 | if (channel == self->priv->channel) | |
199 | { | |
200 | /* fallback to the old-style non interactive TLS verification */ | |
201 | DEBUG ("Channel closed, but unhandled, falling back..."); | |
202 | ||
203 | chainup->verify_async_func (WOCKY_TLS_HANDLER (self), | |
204 | self->priv->tls_session, self->priv->peername, | |
205 | self->priv->reference_identities, verify_fallback_cb, NULL); | |
206 | ||
207 | self->priv->channel = NULL; | |
208 | } | |
209 | else | |
210 | { | |
211 | GList *l; | |
212 | ||
213 | l = g_list_find (self->priv->completed_channels, channel); | |
214 | g_assert (l != NULL); | |
215 | ||
216 | self->priv->completed_channels = g_list_delete_link ( | |
217 | self->priv->completed_channels, l); | |
218 | } | |
219 | ||
220 | tp_channel_manager_emit_channel_closed_for_object (self, | |
221 | TP_EXPORTABLE_CHANNEL (channel)); | |
222 | g_object_unref (channel); | |
223 | } | |
224 | ||
225 | GQuark | |
226 | idle_server_tls_error_quark (void) | |
227 | { | |
228 | static GQuark quark = 0; | |
229 | ||
230 | if (!quark) | |
231 | quark = g_quark_from_static_string ("server-tls-error"); | |
232 | ||
233 | return quark; | |
234 | } | |
235 | ||
236 | static void | |
237 | tls_certificate_accepted_cb (IdleTLSCertificate *certificate, | |
238 | gpointer user_data) | |
239 | { | |
240 | IdleServerTLSManager *self = user_data; | |
241 | ||
242 | DEBUG ("TLS certificate accepted"); | |
243 | ||
244 | complete_verify (self); | |
245 | } | |
246 | ||
247 | static void | |
248 | tls_certificate_rejected_cb (IdleTLSCertificate *certificate, | |
249 | GPtrArray *rejections, | |
250 | gpointer user_data) | |
251 | { | |
252 | IdleServerTLSManager *self = user_data; | |
253 | ||
254 | DEBUG ("TLS certificate rejected with rejections %p, length %u.", | |
255 | rejections, rejections->len); | |
256 | ||
257 | g_simple_async_result_set_error (self->priv->async_result, | |
258 | IDLE_SERVER_TLS_ERROR, 0, "TLS certificate rejected"); | |
259 | ||
260 | complete_verify (self); | |
261 | } | |
262 | ||
263 | static void | |
264 | extend_string_ptr_array (GPtrArray *array, | |
265 | GStrv new_elements) | |
266 | { | |
267 | gint i; | |
268 | ||
269 | if (new_elements != NULL) | |
270 | { | |
271 | for (i = 0; new_elements[i] != NULL; i++) | |
272 | { | |
273 | if (!tp_str_empty (new_elements[i])) | |
274 | g_ptr_array_add (array, g_strdup (new_elements[i])); | |
275 | } | |
276 | } | |
277 | } | |
278 | ||
279 | static void | |
280 | fill_reference_identities (IdleServerTLSManager *self, | |
281 | const gchar *peername, | |
282 | GStrv original_extra_identities) | |
283 | { | |
284 | GPtrArray *identities; | |
285 | gchar *connect_server = NULL; | |
286 | gchar *explicit_server = NULL; | |
287 | GStrv extra_certificate_identities = NULL; | |
288 | ||
289 | g_return_if_fail (self->priv->reference_identities == NULL); | |
290 | ||
291 | g_object_get (self->priv->connection, | |
292 | "connect-server", &connect_server, | |
293 | "explicit-server", &explicit_server, | |
294 | "extra-certificate-identities", &extra_certificate_identities, | |
295 | NULL); | |
296 | ||
297 | identities = g_ptr_array_new (); | |
298 | ||
299 | /* The peer name, i.e, the domain part of the JID */ | |
300 | g_ptr_array_add (identities, g_strdup (peername)); | |
301 | ||
302 | /* The extra identities that the caller of verify_async() passed */ | |
303 | extend_string_ptr_array (identities, original_extra_identities); | |
304 | ||
305 | /* The explicitly overridden server (if in use) */ | |
306 | if (!tp_str_empty (explicit_server) && | |
307 | !tp_strdiff (connect_server, explicit_server)) | |
308 | { | |
309 | g_ptr_array_add (identities, g_strdup (explicit_server)); | |
310 | } | |
311 | ||
312 | /* Extra identities added to the account as a result of user choices */ | |
313 | extend_string_ptr_array (identities, extra_certificate_identities); | |
314 | ||
315 | /* Null terminate, since this is a gchar** */ | |
316 | g_ptr_array_add (identities, NULL); | |
317 | ||
318 | self->priv->reference_identities = (GStrv) g_ptr_array_free (identities, | |
319 | FALSE); | |
320 | ||
321 | g_strfreev (extra_certificate_identities); | |
322 | g_free (explicit_server); | |
323 | g_free (connect_server); | |
324 | } | |
325 | ||
326 | static void | |
327 | idle_server_tls_manager_verify_async (WockyTLSHandler *handler, | |
328 | WockyTLSSession *tls_session, | |
329 | const gchar *peername, | |
330 | GStrv extra_identities, | |
331 | GAsyncReadyCallback callback, | |
332 | gpointer user_data) | |
333 | { | |
334 | IdleServerTLSManager *self = IDLE_SERVER_TLS_MANAGER (handler); | |
335 | IdleTLSCertificate *certificate; | |
336 | GSimpleAsyncResult *result; | |
337 | ||
338 | g_return_if_fail (self->priv->async_result == NULL); | |
339 | ||
340 | DEBUG ("verify_async() called on the IdleServerTLSManager."); | |
341 | ||
342 | result = g_simple_async_result_new (G_OBJECT (self), | |
343 | callback, user_data, idle_server_tls_manager_verify_async); | |
344 | ||
345 | if (self->priv->connection == NULL) | |
346 | { | |
347 | DEBUG ("connection already went away; failing immediately"); | |
348 | g_simple_async_result_set_error (result, TP_ERROR, TP_ERROR_CANCELLED, | |
349 | "The Telepathy connection has already been disconnected"); | |
350 | g_simple_async_result_complete_in_idle (result); | |
351 | g_object_unref (result); | |
352 | return; | |
353 | } | |
354 | ||
355 | self->priv->async_result = result; | |
356 | ||
357 | fill_reference_identities (self, peername, extra_identities); | |
358 | ||
359 | if (!self->priv->interactive_tls) | |
360 | { | |
361 | DEBUG ("ignore-ssl-errors is set, fallback to non-interactive " | |
362 | "verification."); | |
363 | ||
364 | chainup->verify_async_func (WOCKY_TLS_HANDLER (self), tls_session, | |
365 | peername, self->priv->reference_identities, verify_fallback_cb, NULL); | |
366 | ||
367 | return; | |
368 | } | |
369 | ||
370 | self->priv->tls_session = g_object_ref (tls_session); | |
371 | self->priv->peername = g_strdup (peername); | |
372 | ||
373 | self->priv->channel = g_object_new (IDLE_TYPE_SERVER_TLS_CHANNEL, | |
374 | "connection", self->priv->connection, | |
375 | "tls-session", tls_session, | |
376 | "hostname", peername, | |
377 | "reference-identities", self->priv->reference_identities, | |
378 | NULL); | |
379 | ||
380 | g_signal_connect (self->priv->channel, "closed", | |
381 | G_CALLBACK (server_tls_channel_closed_cb), self); | |
382 | ||
383 | certificate = idle_server_tls_channel_get_certificate (self->priv->channel); | |
384 | ||
385 | g_signal_connect (certificate, "accepted", | |
386 | G_CALLBACK (tls_certificate_accepted_cb), self); | |
387 | g_signal_connect (certificate, "rejected", | |
388 | G_CALLBACK (tls_certificate_rejected_cb), self); | |
389 | ||
390 | /* emit NewChannel on the ChannelManager iface */ | |
391 | tp_channel_manager_emit_new_channel (self, | |
392 | (TpExportableChannel *) self->priv->channel, NULL); | |
393 | } | |
394 | ||
395 | static gboolean | |
396 | idle_server_tls_manager_verify_finish (WockyTLSHandler *self, | |
397 | GAsyncResult *result, | |
398 | GError **error) | |
399 | { | |
400 | wocky_implement_finish_void (self, idle_server_tls_manager_verify_async); | |
401 | } | |
402 | ||
403 | static void | |
404 | idle_server_tls_manager_init (IdleServerTLSManager *self) | |
405 | { | |
406 | self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, | |
407 | IDLE_TYPE_SERVER_TLS_MANAGER, IdleServerTLSManagerPrivate); | |
408 | } | |
409 | ||
410 | static void | |
411 | idle_server_tls_manager_dispose (GObject *object) | |
412 | { | |
413 | IdleServerTLSManager *self = IDLE_SERVER_TLS_MANAGER (object); | |
414 | ||
415 | DEBUG ("%p", self); | |
416 | ||
417 | if (self->priv->dispose_has_run) | |
418 | return; | |
419 | ||
420 | self->priv->dispose_has_run = TRUE; | |
421 | ||
422 | tp_clear_object (&self->priv->tls_session); | |
423 | tp_clear_object (&self->priv->connection); | |
424 | ||
425 | G_OBJECT_CLASS (idle_server_tls_manager_parent_class)->dispose (object); | |
426 | } | |
427 | ||
428 | static void | |
429 | idle_server_tls_manager_finalize (GObject *object) | |
430 | { | |
431 | IdleServerTLSManager *self = IDLE_SERVER_TLS_MANAGER (object); | |
432 | ||
433 | DEBUG ("%p", self); | |
434 | ||
435 | close_all (self); | |
436 | ||
437 | g_free (self->priv->peername); | |
438 | g_strfreev (self->priv->reference_identities); | |
439 | ||
440 | G_OBJECT_CLASS (idle_server_tls_manager_parent_class)->finalize (object); | |
441 | } | |
442 | ||
443 | static void | |
444 | idle_server_tls_manager_constructed (GObject *object) | |
445 | { | |
446 | IdleServerTLSManager *self = IDLE_SERVER_TLS_MANAGER (object); | |
447 | void (*chain_up) (GObject *) = | |
448 | G_OBJECT_CLASS (idle_server_tls_manager_parent_class)->constructed; | |
449 | ||
450 | if (chain_up != NULL) | |
451 | chain_up (object); | |
452 | ||
453 | DEBUG ("Server TLS Manager constructed"); | |
454 | ||
455 | idle_signal_connect_weak (self->priv->connection, "status-changed", | |
456 | G_CALLBACK (connection_status_changed_cb), object); | |
457 | } | |
458 | ||
459 | static void | |
460 | idle_server_tls_manager_class_init (IdleServerTLSManagerClass *klass) | |
461 | { | |
462 | GObjectClass *oclass = G_OBJECT_CLASS (klass); | |
463 | WockyTLSHandlerClass *hclass = WOCKY_TLS_HANDLER_CLASS (klass); | |
464 | GParamSpec *pspec; | |
465 | ||
466 | g_type_class_add_private (klass, sizeof (IdleServerTLSManagerPrivate)); | |
467 | ||
468 | oclass->dispose = idle_server_tls_manager_dispose; | |
469 | oclass->finalize = idle_server_tls_manager_finalize; | |
470 | oclass->constructed = idle_server_tls_manager_constructed; | |
471 | oclass->set_property = idle_server_tls_manager_set_property; | |
472 | oclass->get_property = idle_server_tls_manager_get_property; | |
473 | ||
474 | hclass->verify_async_func = idle_server_tls_manager_verify_async; | |
475 | hclass->verify_finish_func = idle_server_tls_manager_verify_finish; | |
476 | ||
477 | pspec = g_param_spec_object ("connection", "IdleConnection object", | |
478 | "Idle connection object that owns this manager.", | |
479 | IDLE_TYPE_CONNECTION, | |
480 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); | |
481 | g_object_class_install_property (oclass, PROP_CONNECTION, pspec); | |
482 | ||
483 | pspec = g_param_spec_boolean ("interactive-tls", "Interactive TLS setting", | |
484 | "Whether interactive TLS certificate verification is enabled.", | |
485 | FALSE, | |
486 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); | |
487 | g_object_class_install_property (oclass, PROP_INTERACTIVE_TLS, pspec); | |
488 | } | |
489 | ||
490 | static void | |
491 | idle_server_tls_manager_foreach_channel (TpChannelManager *manager, | |
492 | TpExportableChannelFunc func, | |
493 | gpointer user_data) | |
494 | { | |
495 | IdleServerTLSManager *self = IDLE_SERVER_TLS_MANAGER (manager); | |
496 | GList *l; | |
497 | ||
498 | if (self->priv->channel != NULL) | |
499 | func (TP_EXPORTABLE_CHANNEL (self->priv->channel), user_data); | |
500 | ||
501 | for (l = self->priv->completed_channels; l != NULL; l = l->next) | |
502 | { | |
503 | func (l->data, user_data); | |
504 | } | |
505 | } | |
506 | ||
507 | static void | |
508 | channel_manager_iface_init (gpointer g_iface, | |
509 | gpointer iface_data) | |
510 | { | |
511 | TpChannelManagerIface *iface = g_iface; | |
512 | ||
513 | iface->foreach_channel = idle_server_tls_manager_foreach_channel; | |
514 | ||
515 | /* these channels are not requestable. */ | |
516 | iface->ensure_channel = NULL; | |
517 | iface->create_channel = NULL; | |
518 | iface->request_channel = NULL; | |
519 | iface->foreach_channel_class = NULL; | |
520 | } | |
521 | ||
522 | static TpConnectionStatusReason | |
523 | cert_reject_reason_to_conn_reason (TpTLSCertificateRejectReason tls_reason) | |
524 | { | |
525 | #define EASY_CASE(x) \ | |
526 | case TP_TLS_CERTIFICATE_REJECT_REASON_ ## x: \ | |
527 | return TP_CONNECTION_STATUS_REASON_CERT_ ## x; | |
528 | ||
529 | switch (tls_reason) | |
530 | { | |
531 | EASY_CASE (UNTRUSTED); | |
532 | EASY_CASE (EXPIRED); | |
533 | EASY_CASE (NOT_ACTIVATED); | |
534 | EASY_CASE (FINGERPRINT_MISMATCH); | |
535 | EASY_CASE (HOSTNAME_MISMATCH); | |
536 | EASY_CASE (SELF_SIGNED); | |
537 | EASY_CASE (REVOKED); | |
538 | EASY_CASE (INSECURE); | |
539 | EASY_CASE (LIMIT_EXCEEDED); | |
540 | ||
541 | case TP_TLS_CERTIFICATE_REJECT_REASON_UNKNOWN: | |
542 | default: | |
543 | return TP_CONNECTION_STATUS_REASON_CERT_OTHER_ERROR; | |
544 | } | |
545 | ||
546 | #undef EASY_CASE | |
547 | } | |
548 | ||
549 | void | |
550 | idle_server_tls_manager_get_rejection_details (IdleServerTLSManager *self, | |
551 | gchar **dbus_error, | |
552 | GHashTable **details, | |
553 | TpConnectionStatusReason *reason) | |
554 | { | |
555 | IdleTLSCertificate *certificate; | |
556 | GPtrArray *rejections; | |
557 | GValueArray *rejection; | |
558 | TpTLSCertificateRejectReason tls_reason; | |
559 | ||
560 | /* We probably want the rejection details of last completed operation */ | |
561 | g_return_if_fail (self->priv->completed_channels != NULL); | |
562 | ||
563 | certificate = idle_server_tls_channel_get_certificate ( | |
564 | self->priv->completed_channels->data); | |
565 | g_object_get (certificate, | |
566 | "rejections", &rejections, | |
567 | NULL); | |
568 | ||
569 | /* we return 'Invalid_Argument' if Reject() is called with zero | |
570 | * reasons, so if this fails something bad happened. | |
571 | */ | |
572 | g_assert (rejections->len >= 1); | |
573 | ||
574 | rejection = g_ptr_array_index (rejections, 0); | |
575 | ||
576 | tls_reason = g_value_get_uint (g_value_array_get_nth (rejection, 0)); | |
577 | *dbus_error = g_value_dup_string (g_value_array_get_nth (rejection, 1)); | |
578 | *details = g_value_dup_boxed (g_value_array_get_nth (rejection, 2)); | |
579 | ||
580 | *reason = cert_reject_reason_to_conn_reason (tls_reason); | |
581 | ||
582 | tp_clear_boxed (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, | |
583 | &rejections); | |
584 | } |
0 | /* | |
1 | * server-tls-manager.h - Header for IdleServerTLSManager | |
2 | * Copyright (C) 2010 Collabora Ltd. | |
3 | * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> | |
4 | * | |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2.1 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this library; if not, write to the Free Software | |
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | */ | |
19 | ||
20 | #ifndef __IDLE_SERVER_TLS_MANAGER_H__ | |
21 | #define __IDLE_SERVER_TLS_MANAGER_H__ | |
22 | ||
23 | #include <glib-object.h> | |
24 | #include <wocky/wocky.h> | |
25 | #include <telepathy-glib/telepathy-glib.h> | |
26 | ||
27 | #include "extensions/extensions.h" | |
28 | ||
29 | G_BEGIN_DECLS | |
30 | ||
31 | typedef struct _IdleServerTLSManager IdleServerTLSManager; | |
32 | typedef struct _IdleServerTLSManagerClass IdleServerTLSManagerClass; | |
33 | typedef struct _IdleServerTLSManagerPrivate IdleServerTLSManagerPrivate; | |
34 | ||
35 | struct _IdleServerTLSManagerClass { | |
36 | WockyTLSHandlerClass parent_class; | |
37 | }; | |
38 | ||
39 | struct _IdleServerTLSManager { | |
40 | WockyTLSHandler parent; | |
41 | IdleServerTLSManagerPrivate *priv; | |
42 | }; | |
43 | ||
44 | GType idle_server_tls_manager_get_type (void); | |
45 | ||
46 | #define IDLE_TYPE_SERVER_TLS_MANAGER \ | |
47 | (idle_server_tls_manager_get_type ()) | |
48 | #define IDLE_SERVER_TLS_MANAGER(obj) \ | |
49 | (G_TYPE_CHECK_INSTANCE_CAST((obj), IDLE_TYPE_SERVER_TLS_MANAGER, \ | |
50 | IdleServerTLSManager)) | |
51 | #define IDLE_SERVER_TLS_MANAGER_CLASS(klass) \ | |
52 | (G_TYPE_CHECK_CLASS_CAST((klass), IDLE_TYPE_SERVER_TLS_MANAGER, \ | |
53 | IdleServerTLSManagerClass)) | |
54 | #define IDLE_IS_SERVER_TLS_MANAGER(obj) \ | |
55 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), IDLE_TYPE_SERVER_TLS_MANAGER)) | |
56 | #define IDLE_IS_SERVER_TLS_MANAGER_CLASS(klass) \ | |
57 | (G_TYPE_CHECK_CLASS_TYPE((klass), IDLE_TYPE_SERVER_TLS_MANAGER)) | |
58 | #define IDLE_SERVER_TLS_MANAGER_GET_CLASS(obj) \ | |
59 | (G_TYPE_INSTANCE_GET_CLASS ((obj), IDLE_TYPE_SERVER_TLS_MANAGER, \ | |
60 | IdleServerTLSManagerClass)) | |
61 | ||
62 | #define IDLE_SERVER_TLS_ERROR idle_server_tls_error_quark () | |
63 | GQuark idle_server_tls_error_quark (void); | |
64 | ||
65 | void idle_server_tls_manager_get_rejection_details ( | |
66 | IdleServerTLSManager *self, | |
67 | gchar **dbus_error, | |
68 | GHashTable **details, | |
69 | TpConnectionStatusReason *reason); | |
70 | ||
71 | G_END_DECLS | |
72 | ||
73 | #endif /* #ifndef __IDLE_SERVER_TLS_MANAGER_H__ */ |
0 | /* | |
1 | * tls-certificate.c - Source for IdleTLSCertificate | |
2 | * Copyright (C) 2010 Collabora Ltd. | |
3 | * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> | |
4 | * | |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2.1 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this library; if not, write to the Free Software | |
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | */ | |
19 | ||
20 | #include "config.h" | |
21 | #include "tls-certificate.h" | |
22 | ||
23 | #include <telepathy-glib/telepathy-glib.h> | |
24 | #include <telepathy-glib/telepathy-glib-dbus.h> | |
25 | ||
26 | #define DEBUG_FLAG IDLE_DEBUG_TLS | |
27 | #include "debug.h" | |
28 | ||
29 | static void | |
30 | tls_certificate_iface_init (gpointer g_iface, gpointer iface_data); | |
31 | ||
32 | G_DEFINE_TYPE_WITH_CODE (IdleTLSCertificate, | |
33 | idle_tls_certificate, | |
34 | G_TYPE_OBJECT, | |
35 | G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_AUTHENTICATION_TLS_CERTIFICATE, | |
36 | tls_certificate_iface_init); | |
37 | G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, | |
38 | tp_dbus_properties_mixin_iface_init);) | |
39 | ||
40 | struct _IdleTLSCertificatePrivate { | |
41 | gchar *object_path; | |
42 | ||
43 | gchar *cert_type; | |
44 | TpTLSCertificateState cert_state; | |
45 | ||
46 | GPtrArray *rejections; | |
47 | GPtrArray *cert_data; | |
48 | ||
49 | TpDBusDaemon *daemon; | |
50 | ||
51 | gboolean dispose_has_run; | |
52 | }; | |
53 | ||
54 | enum { | |
55 | PROP_OBJECT_PATH = 1, | |
56 | PROP_STATE, | |
57 | PROP_REJECTIONS, | |
58 | PROP_CERTIFICATE_TYPE, | |
59 | PROP_CERTIFICATE_CHAIN_DATA, | |
60 | ||
61 | /* not exported */ | |
62 | PROP_DBUS_DAEMON, | |
63 | ||
64 | NUM_PROPERTIES | |
65 | }; | |
66 | ||
67 | static void | |
68 | idle_tls_certificate_get_property (GObject *object, | |
69 | guint property_id, | |
70 | GValue *value, | |
71 | GParamSpec *pspec) | |
72 | { | |
73 | IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (object); | |
74 | ||
75 | switch (property_id) | |
76 | { | |
77 | case PROP_OBJECT_PATH: | |
78 | g_value_set_string (value, self->priv->object_path); | |
79 | break; | |
80 | case PROP_STATE: | |
81 | g_value_set_uint (value, self->priv->cert_state); | |
82 | break; | |
83 | case PROP_REJECTIONS: | |
84 | g_value_set_boxed (value, self->priv->rejections); | |
85 | break; | |
86 | case PROP_CERTIFICATE_TYPE: | |
87 | g_value_set_string (value, self->priv->cert_type); | |
88 | break; | |
89 | case PROP_CERTIFICATE_CHAIN_DATA: | |
90 | g_value_set_boxed (value, self->priv->cert_data); | |
91 | break; | |
92 | default: | |
93 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | |
94 | break; | |
95 | } | |
96 | } | |
97 | ||
98 | static void | |
99 | idle_tls_certificate_set_property (GObject *object, | |
100 | guint property_id, | |
101 | const GValue *value, | |
102 | GParamSpec *pspec) | |
103 | { | |
104 | IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (object); | |
105 | ||
106 | switch (property_id) | |
107 | { | |
108 | case PROP_OBJECT_PATH: | |
109 | self->priv->object_path = g_value_dup_string (value); | |
110 | break; | |
111 | case PROP_CERTIFICATE_TYPE: | |
112 | self->priv->cert_type = g_value_dup_string (value); | |
113 | break; | |
114 | case PROP_CERTIFICATE_CHAIN_DATA: | |
115 | self->priv->cert_data = g_value_dup_boxed (value); | |
116 | break; | |
117 | case PROP_DBUS_DAEMON: | |
118 | self->priv->daemon = g_value_dup_object (value); | |
119 | break; | |
120 | default: | |
121 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, value); | |
122 | break; | |
123 | } | |
124 | } | |
125 | ||
126 | static void | |
127 | idle_tls_certificate_finalize (GObject *object) | |
128 | { | |
129 | IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (object); | |
130 | ||
131 | tp_clear_boxed (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, | |
132 | &self->priv->rejections); | |
133 | ||
134 | g_free (self->priv->object_path); | |
135 | g_free (self->priv->cert_type); | |
136 | g_ptr_array_unref (self->priv->cert_data); | |
137 | ||
138 | G_OBJECT_CLASS (idle_tls_certificate_parent_class)->finalize (object); | |
139 | } | |
140 | ||
141 | static void | |
142 | idle_tls_certificate_dispose (GObject *object) | |
143 | { | |
144 | IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (object); | |
145 | ||
146 | if (self->priv->dispose_has_run) | |
147 | return; | |
148 | ||
149 | self->priv->dispose_has_run = TRUE; | |
150 | ||
151 | tp_clear_object (&self->priv->daemon); | |
152 | ||
153 | G_OBJECT_CLASS (idle_tls_certificate_parent_class)->dispose (object); | |
154 | } | |
155 | ||
156 | static void | |
157 | idle_tls_certificate_constructed (GObject *object) | |
158 | { | |
159 | IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (object); | |
160 | void (*chain_up) (GObject *) = | |
161 | G_OBJECT_CLASS (idle_tls_certificate_parent_class)->constructed; | |
162 | ||
163 | if (chain_up != NULL) | |
164 | chain_up (object); | |
165 | ||
166 | /* register the certificate on the bus */ | |
167 | tp_dbus_daemon_register_object (self->priv->daemon, | |
168 | self->priv->object_path, self); | |
169 | } | |
170 | ||
171 | static void | |
172 | idle_tls_certificate_init (IdleTLSCertificate *self) | |
173 | { | |
174 | self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, | |
175 | IDLE_TYPE_TLS_CERTIFICATE, IdleTLSCertificatePrivate); | |
176 | self->priv->rejections = g_ptr_array_new (); | |
177 | } | |
178 | ||
179 | static void | |
180 | idle_tls_certificate_class_init (IdleTLSCertificateClass *klass) | |
181 | { | |
182 | static TpDBusPropertiesMixinPropImpl object_props[] = { | |
183 | { "State", "state", NULL }, | |
184 | { "Rejections", "rejections", NULL }, | |
185 | { "CertificateType", "certificate-type", NULL }, | |
186 | { "CertificateChainData", "certificate-chain-data", NULL }, | |
187 | { NULL } | |
188 | }; | |
189 | static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { | |
190 | { TP_IFACE_AUTHENTICATION_TLS_CERTIFICATE, | |
191 | tp_dbus_properties_mixin_getter_gobject_properties, | |
192 | NULL, | |
193 | object_props, | |
194 | }, | |
195 | { NULL } | |
196 | }; | |
197 | GObjectClass *oclass = G_OBJECT_CLASS (klass); | |
198 | GParamSpec *pspec; | |
199 | ||
200 | g_type_class_add_private (klass, sizeof (IdleTLSCertificatePrivate)); | |
201 | ||
202 | oclass->finalize = idle_tls_certificate_finalize; | |
203 | oclass->dispose = idle_tls_certificate_dispose; | |
204 | oclass->set_property = idle_tls_certificate_set_property; | |
205 | oclass->get_property = idle_tls_certificate_get_property; | |
206 | oclass->constructed = idle_tls_certificate_constructed; | |
207 | ||
208 | pspec = g_param_spec_string ("object-path", | |
209 | "D-Bus object path", | |
210 | "The D-Bus object path used for this object on the bus.", | |
211 | NULL, | |
212 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); | |
213 | g_object_class_install_property (oclass, PROP_OBJECT_PATH, pspec); | |
214 | ||
215 | pspec = g_param_spec_uint ("state", | |
216 | "State of this certificate", | |
217 | "The state of this TLS certificate.", | |
218 | 0, NUM_TP_TLS_CERTIFICATE_STATES - 1, | |
219 | TP_TLS_CERTIFICATE_STATE_PENDING, | |
220 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); | |
221 | g_object_class_install_property (oclass, PROP_STATE, pspec); | |
222 | ||
223 | pspec = g_param_spec_boxed ("rejections", | |
224 | "The reject reasons", | |
225 | "The reasons why this TLS certificate has been rejected", | |
226 | TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, | |
227 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); | |
228 | g_object_class_install_property (oclass, PROP_REJECTIONS, pspec); | |
229 | ||
230 | pspec = g_param_spec_string ("certificate-type", | |
231 | "The certificate type", | |
232 | "The type of this certificate.", | |
233 | NULL, | |
234 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); | |
235 | g_object_class_install_property (oclass, PROP_CERTIFICATE_TYPE, pspec); | |
236 | ||
237 | pspec = g_param_spec_boxed ("certificate-chain-data", | |
238 | "The certificate chain data", | |
239 | "The raw PEM-encoded trust chain of this certificate.", | |
240 | TP_ARRAY_TYPE_UCHAR_ARRAY_LIST, | |
241 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); | |
242 | g_object_class_install_property (oclass, PROP_CERTIFICATE_CHAIN_DATA, pspec); | |
243 | ||
244 | pspec = g_param_spec_object ("dbus-daemon", | |
245 | "The DBus daemon connection", | |
246 | "The connection to the DBus daemon owning the CM", | |
247 | TP_TYPE_DBUS_DAEMON, | |
248 | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); | |
249 | g_object_class_install_property (oclass, PROP_DBUS_DAEMON, pspec); | |
250 | ||
251 | klass->dbus_props_class.interfaces = prop_interfaces; | |
252 | tp_dbus_properties_mixin_class_init (oclass, | |
253 | G_STRUCT_OFFSET (IdleTLSCertificateClass, dbus_props_class)); | |
254 | } | |
255 | ||
256 | static void | |
257 | idle_tls_certificate_accept (TpSvcAuthenticationTLSCertificate *cert, | |
258 | DBusGMethodInvocation *context) | |
259 | { | |
260 | IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (cert); | |
261 | ||
262 | DEBUG ("Accept() called on the TLS certificate; current state %u", | |
263 | self->priv->cert_state); | |
264 | ||
265 | if (self->priv->cert_state != TP_TLS_CERTIFICATE_STATE_PENDING) | |
266 | { | |
267 | GError error = | |
268 | { TP_ERROR, | |
269 | TP_ERROR_INVALID_ARGUMENT, | |
270 | "Calling Accept() on a certificate with state != PENDING " | |
271 | "doesn't make sense." | |
272 | }; | |
273 | ||
274 | dbus_g_method_return_error (context, &error); | |
275 | return; | |
276 | } | |
277 | ||
278 | self->priv->cert_state = TP_TLS_CERTIFICATE_STATE_ACCEPTED; | |
279 | tp_svc_authentication_tls_certificate_emit_accepted (self); | |
280 | ||
281 | tp_svc_authentication_tls_certificate_return_from_accept (context); | |
282 | } | |
283 | ||
284 | static void | |
285 | idle_tls_certificate_reject (TpSvcAuthenticationTLSCertificate *cert, | |
286 | const GPtrArray *rejections, | |
287 | DBusGMethodInvocation *context) | |
288 | { | |
289 | IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (cert); | |
290 | ||
291 | DEBUG ("Reject() called on the TLS certificate with rejections %p, " | |
292 | "length %u; current state %u", rejections, rejections->len, | |
293 | self->priv->cert_state); | |
294 | ||
295 | if (rejections->len < 1) | |
296 | { | |
297 | GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, | |
298 | "Calling Reject() with a zero-length rejection list." }; | |
299 | ||
300 | dbus_g_method_return_error (context, &error); | |
301 | return; | |
302 | } | |
303 | ||
304 | if (self->priv->cert_state != TP_TLS_CERTIFICATE_STATE_PENDING) | |
305 | { | |
306 | GError error = | |
307 | { TP_ERROR, | |
308 | TP_ERROR_INVALID_ARGUMENT, | |
309 | "Calling Reject() on a certificate with state != PENDING " | |
310 | "doesn't make sense." | |
311 | }; | |
312 | ||
313 | dbus_g_method_return_error (context, &error); | |
314 | return; | |
315 | } | |
316 | ||
317 | tp_clear_boxed (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, | |
318 | &self->priv->rejections); | |
319 | ||
320 | self->priv->rejections = | |
321 | g_boxed_copy (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, | |
322 | rejections); | |
323 | self->priv->cert_state = TP_TLS_CERTIFICATE_STATE_REJECTED; | |
324 | ||
325 | tp_svc_authentication_tls_certificate_emit_rejected ( | |
326 | self, self->priv->rejections); | |
327 | ||
328 | tp_svc_authentication_tls_certificate_return_from_reject (context); | |
329 | } | |
330 | ||
331 | static void | |
332 | tls_certificate_iface_init (gpointer g_iface, | |
333 | gpointer iface_data) | |
334 | { | |
335 | TpSvcAuthenticationTLSCertificateClass *klass = g_iface; | |
336 | ||
337 | #define IMPLEMENT(x) \ | |
338 | tp_svc_authentication_tls_certificate_implement_##x ( \ | |
339 | klass, idle_tls_certificate_##x) | |
340 | IMPLEMENT (accept); | |
341 | IMPLEMENT (reject); | |
342 | #undef IMPLEMENT | |
343 | } |
0 | /* | |
1 | * tls-certificate.h - Header for IdleTLSCertificate | |
2 | * Copyright (C) 2010 Collabora Ltd. | |
3 | * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> | |
4 | * | |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2.1 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this library; if not, write to the Free Software | |
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | */ | |
19 | ||
20 | #ifndef __IDLE_TLS_CERTIFICATE_H__ | |
21 | #define __IDLE_TLS_CERTIFICATE_H__ | |
22 | ||
23 | #include <glib-object.h> | |
24 | ||
25 | #include <telepathy-glib/telepathy-glib.h> | |
26 | ||
27 | G_BEGIN_DECLS | |
28 | ||
29 | typedef struct _IdleTLSCertificate IdleTLSCertificate; | |
30 | typedef struct _IdleTLSCertificateClass IdleTLSCertificateClass; | |
31 | typedef struct _IdleTLSCertificatePrivate IdleTLSCertificatePrivate; | |
32 | ||
33 | struct _IdleTLSCertificateClass { | |
34 | GObjectClass parent_class; | |
35 | ||
36 | TpDBusPropertiesMixinClass dbus_props_class; | |
37 | }; | |
38 | ||
39 | struct _IdleTLSCertificate { | |
40 | GObject parent; | |
41 | ||
42 | IdleTLSCertificatePrivate *priv; | |
43 | }; | |
44 | ||
45 | GType idle_tls_certificate_get_type (void); | |
46 | ||
47 | #define IDLE_TYPE_TLS_CERTIFICATE \ | |
48 | (idle_tls_certificate_get_type ()) | |
49 | #define IDLE_TLS_CERTIFICATE(obj) \ | |
50 | (G_TYPE_CHECK_INSTANCE_CAST((obj), IDLE_TYPE_TLS_CERTIFICATE, \ | |
51 | IdleTLSCertificate)) | |
52 | #define IDLE_TLS_CERTIFICATE_CLASS(klass) \ | |
53 | (G_TYPE_CHECK_CLASS_CAST((klass), IDLE_TYPE_TLS_CERTIFICATE, \ | |
54 | IdleTLSCertificateClass)) | |
55 | #define IDLE_IS_TLS_CERTIFICATE(obj) \ | |
56 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), IDLE_TYPE_TLS_CERTIFICATE)) | |
57 | #define IDLE_IS_TLS_CERTIFICATE_CLASS(klass) \ | |
58 | (G_TYPE_CHECK_CLASS_TYPE((klass), IDLE_TYPE_TLS_CERTIFICATE)) | |
59 | #define IDLE_TLS_CERTIFICATE_GET_CLASS(obj) \ | |
60 | (G_TYPE_INSTANCE_GET_CLASS ((obj), IDLE_TYPE_TLS_CERTIFICATE, \ | |
61 | IdleTLSCertificateClass)) | |
62 | ||
63 | G_END_DECLS | |
64 | ||
65 | #endif /* #ifndef __IDLE_TLS_CERTIFICATE_H__*/ |