1 /* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright (C) 2011 Collabora Ltd.
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
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "gtesttlsbackend.h"
20
21 #include <glib.h>
22
23 static GType _g_test_tls_certificate_get_type (void);
24 static GType _g_test_tls_connection_get_type (void);
25 static GTlsDatabase * _g_test_tls_backend_get_default_database (GTlsBackend * backend);
26 static GType _g_test_tls_database_get_type (void);
27
28 struct _GTestTlsBackend {
29 GObject parent_instance;
30 };
31
32 static void g_test_tls_backend_iface_init (GTlsBackendInterface *iface);
33
34 #define g_test_tls_backend_get_type _g_test_tls_backend_get_type
35 G_DEFINE_TYPE_WITH_CODE (GTestTlsBackend, g_test_tls_backend, G_TYPE_OBJECT,
36 G_IMPLEMENT_INTERFACE (G_TYPE_TLS_BACKEND,
37 g_test_tls_backend_iface_init)
38 g_io_extension_point_set_required_type (
39 g_io_extension_point_register (G_TLS_BACKEND_EXTENSION_POINT_NAME),
40 G_TYPE_TLS_BACKEND);
41 g_io_extension_point_implement (G_TLS_BACKEND_EXTENSION_POINT_NAME,
42 g_define_type_id,
43 "test",
44 999);)
45
46 static void
g_test_tls_backend_init(GTestTlsBackend * backend)47 g_test_tls_backend_init (GTestTlsBackend *backend)
48 {
49 }
50
51 static void
g_test_tls_backend_class_init(GTestTlsBackendClass * backend_class)52 g_test_tls_backend_class_init (GTestTlsBackendClass *backend_class)
53 {
54 }
55
56 static void
g_test_tls_backend_iface_init(GTlsBackendInterface * iface)57 g_test_tls_backend_iface_init (GTlsBackendInterface *iface)
58 {
59 iface->get_certificate_type = _g_test_tls_certificate_get_type;
60 iface->get_client_connection_type = _g_test_tls_connection_get_type;
61 iface->get_server_connection_type = _g_test_tls_connection_get_type;
62 iface->get_dtls_client_connection_type = _g_test_tls_connection_get_type;
63 iface->get_dtls_server_connection_type = _g_test_tls_connection_get_type;
64 iface->get_default_database = _g_test_tls_backend_get_default_database;
65 iface->get_file_database_type = _g_test_tls_database_get_type;
66 }
67
68 static GTlsDatabase *
_g_test_tls_backend_get_default_database(GTlsBackend * backend)69 _g_test_tls_backend_get_default_database (GTlsBackend * backend)
70 {
71 static GTlsDatabase *default_db;
72 GError *error = NULL;
73
74 if (!default_db)
75 {
76 default_db = g_initable_new (_g_test_tls_database_get_type (),
77 NULL,
78 &error,
79 NULL);
80 g_assert_no_error (error);
81 }
82
83 return default_db;
84 }
85
86 /* Test certificate type */
87
88 typedef struct _GTestTlsCertificate GTestTlsCertificate;
89 typedef struct _GTestTlsCertificateClass GTestTlsCertificateClass;
90
91 struct _GTestTlsCertificate {
92 GTlsCertificate parent_instance;
93 gchar *key_pem;
94 gchar *cert_pem;
95 GTlsCertificate *issuer;
96 gchar *pkcs11_uri;
97 gchar *private_key_pkcs11_uri;
98 };
99
100 struct _GTestTlsCertificateClass {
101 GTlsCertificateClass parent_class;
102 };
103
104 enum
105 {
106 PROP_CERT_CERTIFICATE = 1,
107 PROP_CERT_CERTIFICATE_PEM,
108 PROP_CERT_PRIVATE_KEY,
109 PROP_CERT_PRIVATE_KEY_PEM,
110 PROP_CERT_ISSUER,
111 PROP_CERT_PKCS11_URI,
112 PROP_CERT_PRIVATE_KEY_PKCS11_URI,
113 };
114
115 static void g_test_tls_certificate_initable_iface_init (GInitableIface *iface);
116
117 #define g_test_tls_certificate_get_type _g_test_tls_certificate_get_type
G_DEFINE_TYPE_WITH_CODE(GTestTlsCertificate,g_test_tls_certificate,G_TYPE_TLS_CERTIFICATE,G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,g_test_tls_certificate_initable_iface_init))118 G_DEFINE_TYPE_WITH_CODE (GTestTlsCertificate, g_test_tls_certificate, G_TYPE_TLS_CERTIFICATE,
119 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
120 g_test_tls_certificate_initable_iface_init))
121
122 static GTlsCertificateFlags
123 g_test_tls_certificate_verify (GTlsCertificate *cert,
124 GSocketConnectable *identity,
125 GTlsCertificate *trusted_ca)
126 {
127 /* For now, all of the tests expect the certificate to verify */
128 return 0;
129 }
130
131 static void
g_test_tls_certificate_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)132 g_test_tls_certificate_get_property (GObject *object,
133 guint prop_id,
134 GValue *value,
135 GParamSpec *pspec)
136 {
137 GTestTlsCertificate *cert = (GTestTlsCertificate *) object;
138
139 switch (prop_id)
140 {
141 case PROP_CERT_CERTIFICATE_PEM:
142 g_value_set_string (value, cert->cert_pem);
143 break;
144 case PROP_CERT_PRIVATE_KEY_PEM:
145 g_value_set_string (value, cert->key_pem);
146 break;
147 case PROP_CERT_ISSUER:
148 g_value_set_object (value, cert->issuer);
149 break;
150 case PROP_CERT_PKCS11_URI:
151 /* This test value simulates a backend that ignores the value
152 because it is unsupported */
153 if (g_strcmp0 (cert->pkcs11_uri, "unsupported") != 0)
154 g_value_set_string (value, cert->pkcs11_uri);
155 break;
156 case PROP_CERT_PRIVATE_KEY_PKCS11_URI:
157 g_value_set_string (value, cert->private_key_pkcs11_uri);
158 break;
159 default:
160 g_assert_not_reached ();
161 break;
162 }
163 }
164
165 static void
g_test_tls_certificate_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)166 g_test_tls_certificate_set_property (GObject *object,
167 guint prop_id,
168 const GValue *value,
169 GParamSpec *pspec)
170 {
171 GTestTlsCertificate *cert = (GTestTlsCertificate *) object;
172
173 switch (prop_id)
174 {
175 case PROP_CERT_CERTIFICATE_PEM:
176 cert->cert_pem = g_value_dup_string (value);
177 break;
178 case PROP_CERT_PRIVATE_KEY_PEM:
179 cert->key_pem = g_value_dup_string (value);
180 break;
181 case PROP_CERT_ISSUER:
182 cert->issuer = g_value_dup_object (value);
183 break;
184 case PROP_CERT_PKCS11_URI:
185 cert->pkcs11_uri = g_value_dup_string (value);
186 break;
187 case PROP_CERT_PRIVATE_KEY_PKCS11_URI:
188 cert->private_key_pkcs11_uri = g_value_dup_string (value);
189 break;
190 case PROP_CERT_CERTIFICATE:
191 case PROP_CERT_PRIVATE_KEY:
192 /* ignore */
193 break;
194 default:
195 g_assert_not_reached ();
196 break;
197 }
198 }
199
200 static void
g_test_tls_certificate_finalize(GObject * object)201 g_test_tls_certificate_finalize (GObject *object)
202 {
203 GTestTlsCertificate *cert = (GTestTlsCertificate *) object;
204
205 g_free (cert->cert_pem);
206 g_free (cert->key_pem);
207 g_free (cert->pkcs11_uri);
208 g_free (cert->private_key_pkcs11_uri);
209 g_clear_object (&cert->issuer);
210
211 G_OBJECT_CLASS (g_test_tls_certificate_parent_class)->finalize (object);
212 }
213
214 static void
g_test_tls_certificate_class_init(GTestTlsCertificateClass * test_class)215 g_test_tls_certificate_class_init (GTestTlsCertificateClass *test_class)
216 {
217 GObjectClass *gobject_class = G_OBJECT_CLASS (test_class);
218 GTlsCertificateClass *certificate_class = G_TLS_CERTIFICATE_CLASS (test_class);
219
220 gobject_class->get_property = g_test_tls_certificate_get_property;
221 gobject_class->set_property = g_test_tls_certificate_set_property;
222 gobject_class->finalize = g_test_tls_certificate_finalize;
223
224 certificate_class->verify = g_test_tls_certificate_verify;
225
226 g_object_class_override_property (gobject_class, PROP_CERT_CERTIFICATE, "certificate");
227 g_object_class_override_property (gobject_class, PROP_CERT_CERTIFICATE_PEM, "certificate-pem");
228 g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY, "private-key");
229 g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY_PEM, "private-key-pem");
230 g_object_class_override_property (gobject_class, PROP_CERT_ISSUER, "issuer");
231 g_object_class_override_property (gobject_class, PROP_CERT_PKCS11_URI, "pkcs11-uri");
232 g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY_PKCS11_URI, "private-key-pkcs11-uri");
233 }
234
235 static void
g_test_tls_certificate_init(GTestTlsCertificate * certificate)236 g_test_tls_certificate_init (GTestTlsCertificate *certificate)
237 {
238 }
239
240 static gboolean
g_test_tls_certificate_initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)241 g_test_tls_certificate_initable_init (GInitable *initable,
242 GCancellable *cancellable,
243 GError **error)
244 {
245 return TRUE;
246 }
247
248 static void
g_test_tls_certificate_initable_iface_init(GInitableIface * iface)249 g_test_tls_certificate_initable_iface_init (GInitableIface *iface)
250 {
251 iface->init = g_test_tls_certificate_initable_init;
252 }
253
254 /* Dummy connection type; since GTlsClientConnection and
255 * GTlsServerConnection are just interfaces, we can implement them
256 * both on a single object.
257 */
258
259 typedef struct _GTestTlsConnection GTestTlsConnection;
260 typedef struct _GTestTlsConnectionClass GTestTlsConnectionClass;
261
262 struct _GTestTlsConnection {
263 GTlsConnection parent_instance;
264 };
265
266 struct _GTestTlsConnectionClass {
267 GTlsConnectionClass parent_class;
268 };
269
270 enum
271 {
272 PROP_CONN_BASE_IO_STREAM = 1,
273 PROP_CONN_BASE_SOCKET,
274 PROP_CONN_USE_SYSTEM_CERTDB,
275 PROP_CONN_REQUIRE_CLOSE_NOTIFY,
276 PROP_CONN_REHANDSHAKE_MODE,
277 PROP_CONN_CERTIFICATE,
278 PROP_CONN_PEER_CERTIFICATE,
279 PROP_CONN_PEER_CERTIFICATE_ERRORS,
280 PROP_CONN_VALIDATION_FLAGS,
281 PROP_CONN_SERVER_IDENTITY,
282 PROP_CONN_USE_SSL3,
283 PROP_CONN_ACCEPTED_CAS,
284 PROP_CONN_AUTHENTICATION_MODE
285 };
286
287 static void g_test_tls_connection_initable_iface_init (GInitableIface *iface);
288
289 #define g_test_tls_connection_get_type _g_test_tls_connection_get_type
G_DEFINE_TYPE_WITH_CODE(GTestTlsConnection,g_test_tls_connection,G_TYPE_TLS_CONNECTION,G_IMPLEMENT_INTERFACE (G_TYPE_TLS_CLIENT_CONNECTION,NULL)G_IMPLEMENT_INTERFACE (G_TYPE_TLS_SERVER_CONNECTION,NULL)G_IMPLEMENT_INTERFACE (G_TYPE_DATAGRAM_BASED,NULL)G_IMPLEMENT_INTERFACE (G_TYPE_DTLS_CONNECTION,NULL)G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,g_test_tls_connection_initable_iface_init))290 G_DEFINE_TYPE_WITH_CODE (GTestTlsConnection, g_test_tls_connection, G_TYPE_TLS_CONNECTION,
291 G_IMPLEMENT_INTERFACE (G_TYPE_TLS_CLIENT_CONNECTION, NULL)
292 G_IMPLEMENT_INTERFACE (G_TYPE_TLS_SERVER_CONNECTION, NULL)
293 G_IMPLEMENT_INTERFACE (G_TYPE_DATAGRAM_BASED, NULL)
294 G_IMPLEMENT_INTERFACE (G_TYPE_DTLS_CONNECTION, NULL)
295 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
296 g_test_tls_connection_initable_iface_init))
297
298 static void
299 g_test_tls_connection_get_property (GObject *object,
300 guint prop_id,
301 GValue *value,
302 GParamSpec *pspec)
303 {
304 }
305
306 static void
g_test_tls_connection_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)307 g_test_tls_connection_set_property (GObject *object,
308 guint prop_id,
309 const GValue *value,
310 GParamSpec *pspec)
311 {
312 }
313
314 static gboolean
g_test_tls_connection_close(GIOStream * stream,GCancellable * cancellable,GError ** error)315 g_test_tls_connection_close (GIOStream *stream,
316 GCancellable *cancellable,
317 GError **error)
318 {
319 return TRUE;
320 }
321
322 static void
g_test_tls_connection_class_init(GTestTlsConnectionClass * connection_class)323 g_test_tls_connection_class_init (GTestTlsConnectionClass *connection_class)
324 {
325 GObjectClass *gobject_class = G_OBJECT_CLASS (connection_class);
326 GIOStreamClass *io_stream_class = G_IO_STREAM_CLASS (connection_class);
327
328 gobject_class->get_property = g_test_tls_connection_get_property;
329 gobject_class->set_property = g_test_tls_connection_set_property;
330
331 /* Need to override this because when initable_init fails it will
332 * dispose the connection, which will close it, which would
333 * otherwise try to close its input/output streams, which don't
334 * exist.
335 */
336 io_stream_class->close_fn = g_test_tls_connection_close;
337
338 g_object_class_override_property (gobject_class, PROP_CONN_BASE_IO_STREAM, "base-io-stream");
339 g_object_class_override_property (gobject_class, PROP_CONN_BASE_SOCKET, "base-socket");
340 g_object_class_override_property (gobject_class, PROP_CONN_USE_SYSTEM_CERTDB, "use-system-certdb");
341 g_object_class_override_property (gobject_class, PROP_CONN_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
342 g_object_class_override_property (gobject_class, PROP_CONN_REHANDSHAKE_MODE, "rehandshake-mode");
343 g_object_class_override_property (gobject_class, PROP_CONN_CERTIFICATE, "certificate");
344 g_object_class_override_property (gobject_class, PROP_CONN_PEER_CERTIFICATE, "peer-certificate");
345 g_object_class_override_property (gobject_class, PROP_CONN_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
346 g_object_class_override_property (gobject_class, PROP_CONN_VALIDATION_FLAGS, "validation-flags");
347 g_object_class_override_property (gobject_class, PROP_CONN_SERVER_IDENTITY, "server-identity");
348 g_object_class_override_property (gobject_class, PROP_CONN_USE_SSL3, "use-ssl3");
349 g_object_class_override_property (gobject_class, PROP_CONN_ACCEPTED_CAS, "accepted-cas");
350 g_object_class_override_property (gobject_class, PROP_CONN_AUTHENTICATION_MODE, "authentication-mode");
351 }
352
353 static void
g_test_tls_connection_init(GTestTlsConnection * connection)354 g_test_tls_connection_init (GTestTlsConnection *connection)
355 {
356 }
357
358 static gboolean
g_test_tls_connection_initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)359 g_test_tls_connection_initable_init (GInitable *initable,
360 GCancellable *cancellable,
361 GError **error)
362 {
363 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_UNAVAILABLE,
364 "TLS Connection support is not available");
365 return FALSE;
366 }
367
368 static void
g_test_tls_connection_initable_iface_init(GInitableIface * iface)369 g_test_tls_connection_initable_iface_init (GInitableIface *iface)
370 {
371 iface->init = g_test_tls_connection_initable_init;
372 }
373
374 const gchar *
g_test_tls_connection_get_private_key_pem(GTlsCertificate * cert)375 g_test_tls_connection_get_private_key_pem (GTlsCertificate *cert)
376 {
377 return ((GTestTlsCertificate *)cert)->key_pem;
378 }
379
380 /* Test database type */
381
382 typedef struct _GTestTlsDatabase GTestTlsDatabase;
383 typedef struct _GTestTlsDatabaseClass GTestTlsDatabaseClass;
384
385 struct _GTestTlsDatabase {
386 GTlsDatabase parent_instance;
387 gchar *anchors;
388 };
389
390 struct _GTestTlsDatabaseClass {
391 GTlsDatabaseClass parent_class;
392 };
393
394 enum
395 {
396 PROP_DATABASE_ANCHORS = 1,
397 };
398
399 static void g_test_tls_database_initable_iface_init (GInitableIface *iface);
400 static void g_test_tls_file_database_file_database_interface_init (GInitableIface *iface);
401
402 #define g_test_tls_database_get_type _g_test_tls_database_get_type
G_DEFINE_TYPE_WITH_CODE(GTestTlsDatabase,g_test_tls_database,G_TYPE_TLS_DATABASE,G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,g_test_tls_database_initable_iface_init);G_IMPLEMENT_INTERFACE (G_TYPE_TLS_FILE_DATABASE,g_test_tls_file_database_file_database_interface_init))403 G_DEFINE_TYPE_WITH_CODE (GTestTlsDatabase, g_test_tls_database, G_TYPE_TLS_DATABASE,
404 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
405 g_test_tls_database_initable_iface_init);
406 G_IMPLEMENT_INTERFACE (G_TYPE_TLS_FILE_DATABASE,
407 g_test_tls_file_database_file_database_interface_init))
408
409 static void
410 g_test_tls_database_get_property (GObject *object,
411 guint prop_id,
412 GValue *value,
413 GParamSpec *pspec)
414 {
415 GTestTlsDatabase *db = (GTestTlsDatabase *) object;
416
417 switch (prop_id)
418 {
419 case PROP_DATABASE_ANCHORS:
420 g_value_set_string (value, db->anchors);
421 break;
422 default:
423 g_assert_not_reached ();
424 break;
425 }
426 }
427
428 static void
g_test_tls_database_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)429 g_test_tls_database_set_property (GObject *object,
430 guint prop_id,
431 const GValue *value,
432 GParamSpec *pspec)
433 {
434 GTestTlsDatabase *db = (GTestTlsDatabase *) object;
435
436 switch (prop_id)
437 {
438 case PROP_DATABASE_ANCHORS:
439 g_free (db->anchors);
440 db->anchors = g_value_dup_string (value);
441 break;
442 default:
443 g_assert_not_reached ();
444 break;
445 }
446 }
447
448 static void
g_test_tls_database_finalize(GObject * object)449 g_test_tls_database_finalize (GObject *object)
450 {
451 GTestTlsDatabase *db = (GTestTlsDatabase *) object;
452
453 g_free (db->anchors);
454
455 G_OBJECT_CLASS (g_test_tls_database_parent_class)->finalize (object);
456 }
457
458 static void
g_test_tls_database_class_init(GTestTlsDatabaseClass * test_class)459 g_test_tls_database_class_init (GTestTlsDatabaseClass *test_class)
460 {
461 GObjectClass *gobject_class = G_OBJECT_CLASS (test_class);
462
463 gobject_class->get_property = g_test_tls_database_get_property;
464 gobject_class->set_property = g_test_tls_database_set_property;
465 gobject_class->finalize = g_test_tls_database_finalize;
466
467 g_object_class_override_property (gobject_class, PROP_DATABASE_ANCHORS, "anchors");
468 }
469
470 static void
g_test_tls_database_init(GTestTlsDatabase * database)471 g_test_tls_database_init (GTestTlsDatabase *database)
472 {
473 }
474
475 static gboolean
g_test_tls_database_initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)476 g_test_tls_database_initable_init (GInitable *initable,
477 GCancellable *cancellable,
478 GError **error)
479 {
480 return TRUE;
481 }
482
483 static void
g_test_tls_file_database_file_database_interface_init(GInitableIface * iface)484 g_test_tls_file_database_file_database_interface_init (GInitableIface *iface)
485 {
486 }
487
488 static void
g_test_tls_database_initable_iface_init(GInitableIface * iface)489 g_test_tls_database_initable_iface_init (GInitableIface *iface)
490 {
491 iface->init = g_test_tls_database_initable_init;
492 }
493