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
23static GType _g_test_tls_certificate_get_type (void);
24static GType _g_test_tls_connection_get_type (void);
25static GTlsDatabase * _g_test_tls_backend_get_default_database (GTlsBackend * backend);
26static GType _g_test_tls_database_get_type (void);
27
28struct _GTestTlsBackend {
29 GObject parent_instance;
30};
31
32static void g_test_tls_backend_iface_init (GTlsBackendInterface *iface);
33
34#define g_test_tls_backend_get_type _g_test_tls_backend_get_type
35G_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
46static void
47g_test_tls_backend_init (GTestTlsBackend *backend)
48{
49}
50
51static void
52g_test_tls_backend_class_init (GTestTlsBackendClass *backend_class)
53{
54}
55
56static void
57g_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
68static GTlsDatabase *
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 (object_type: _g_test_tls_database_get_type (),
77 NULL,
78 error: &error,
79 NULL);
80 g_assert_no_error (error);
81 }
82
83 return default_db;
84}
85
86/* Test certificate type */
87
88typedef struct _GTestTlsCertificate GTestTlsCertificate;
89typedef struct _GTestTlsCertificateClass GTestTlsCertificateClass;
90
91struct _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
100struct _GTestTlsCertificateClass {
101 GTlsCertificateClass parent_class;
102};
103
104enum
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
115static 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
118G_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
122static GTlsCertificateFlags
123g_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
131static void
132g_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, v_string: cert->cert_pem);
143 break;
144 case PROP_CERT_PRIVATE_KEY_PEM:
145 g_value_set_string (value, v_string: cert->key_pem);
146 break;
147 case PROP_CERT_ISSUER:
148 g_value_set_object (value, v_object: 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 (str1: cert->pkcs11_uri, str2: "unsupported") != 0)
154 g_value_set_string (value, v_string: cert->pkcs11_uri);
155 break;
156 case PROP_CERT_PRIVATE_KEY_PKCS11_URI:
157 g_value_set_string (value, v_string: cert->private_key_pkcs11_uri);
158 break;
159 default:
160 g_assert_not_reached ();
161 break;
162 }
163}
164
165static void
166g_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
200static void
201g_test_tls_certificate_finalize (GObject *object)
202{
203 GTestTlsCertificate *cert = (GTestTlsCertificate *) object;
204
205 g_free (mem: cert->cert_pem);
206 g_free (mem: cert->key_pem);
207 g_free (mem: cert->pkcs11_uri);
208 g_free (mem: 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
214static void
215g_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 (oclass: gobject_class, property_id: PROP_CERT_CERTIFICATE, name: "certificate");
227 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CERT_CERTIFICATE_PEM, name: "certificate-pem");
228 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CERT_PRIVATE_KEY, name: "private-key");
229 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CERT_PRIVATE_KEY_PEM, name: "private-key-pem");
230 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CERT_ISSUER, name: "issuer");
231 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CERT_PKCS11_URI, name: "pkcs11-uri");
232 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CERT_PRIVATE_KEY_PKCS11_URI, name: "private-key-pkcs11-uri");
233}
234
235static void
236g_test_tls_certificate_init (GTestTlsCertificate *certificate)
237{
238}
239
240static gboolean
241g_test_tls_certificate_initable_init (GInitable *initable,
242 GCancellable *cancellable,
243 GError **error)
244{
245 return TRUE;
246}
247
248static void
249g_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
259typedef struct _GTestTlsConnection GTestTlsConnection;
260typedef struct _GTestTlsConnectionClass GTestTlsConnectionClass;
261
262struct _GTestTlsConnection {
263 GTlsConnection parent_instance;
264};
265
266struct _GTestTlsConnectionClass {
267 GTlsConnectionClass parent_class;
268};
269
270enum
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
287static 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
290G_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
298static void
299g_test_tls_connection_get_property (GObject *object,
300 guint prop_id,
301 GValue *value,
302 GParamSpec *pspec)
303{
304}
305
306static void
307g_test_tls_connection_set_property (GObject *object,
308 guint prop_id,
309 const GValue *value,
310 GParamSpec *pspec)
311{
312}
313
314static gboolean
315g_test_tls_connection_close (GIOStream *stream,
316 GCancellable *cancellable,
317 GError **error)
318{
319 return TRUE;
320}
321
322static void
323g_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 (oclass: gobject_class, property_id: PROP_CONN_BASE_IO_STREAM, name: "base-io-stream");
339 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_BASE_SOCKET, name: "base-socket");
340 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_USE_SYSTEM_CERTDB, name: "use-system-certdb");
341 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_REQUIRE_CLOSE_NOTIFY, name: "require-close-notify");
342 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_REHANDSHAKE_MODE, name: "rehandshake-mode");
343 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_CERTIFICATE, name: "certificate");
344 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_PEER_CERTIFICATE, name: "peer-certificate");
345 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_PEER_CERTIFICATE_ERRORS, name: "peer-certificate-errors");
346 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_VALIDATION_FLAGS, name: "validation-flags");
347 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_SERVER_IDENTITY, name: "server-identity");
348 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_USE_SSL3, name: "use-ssl3");
349 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_ACCEPTED_CAS, name: "accepted-cas");
350 g_object_class_override_property (oclass: gobject_class, property_id: PROP_CONN_AUTHENTICATION_MODE, name: "authentication-mode");
351}
352
353static void
354g_test_tls_connection_init (GTestTlsConnection *connection)
355{
356}
357
358static gboolean
359g_test_tls_connection_initable_init (GInitable *initable,
360 GCancellable *cancellable,
361 GError **error)
362{
363 g_set_error_literal (err: error, G_TLS_ERROR, code: G_TLS_ERROR_UNAVAILABLE,
364 message: "TLS Connection support is not available");
365 return FALSE;
366}
367
368static void
369g_test_tls_connection_initable_iface_init (GInitableIface *iface)
370{
371 iface->init = g_test_tls_connection_initable_init;
372}
373
374const gchar *
375g_test_tls_connection_get_private_key_pem (GTlsCertificate *cert)
376{
377 return ((GTestTlsCertificate *)cert)->key_pem;
378}
379
380/* Test database type */
381
382typedef struct _GTestTlsDatabase GTestTlsDatabase;
383typedef struct _GTestTlsDatabaseClass GTestTlsDatabaseClass;
384
385struct _GTestTlsDatabase {
386 GTlsDatabase parent_instance;
387 gchar *anchors;
388};
389
390struct _GTestTlsDatabaseClass {
391 GTlsDatabaseClass parent_class;
392};
393
394enum
395{
396 PROP_DATABASE_ANCHORS = 1,
397};
398
399static void g_test_tls_database_initable_iface_init (GInitableIface *iface);
400static 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
403G_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
409static void
410g_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, v_string: db->anchors);
421 break;
422 default:
423 g_assert_not_reached ();
424 break;
425 }
426}
427
428static void
429g_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 (mem: db->anchors);
440 db->anchors = g_value_dup_string (value);
441 break;
442 default:
443 g_assert_not_reached ();
444 break;
445 }
446}
447
448static void
449g_test_tls_database_finalize (GObject *object)
450{
451 GTestTlsDatabase *db = (GTestTlsDatabase *) object;
452
453 g_free (mem: db->anchors);
454
455 G_OBJECT_CLASS (g_test_tls_database_parent_class)->finalize (object);
456}
457
458static void
459g_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 (oclass: gobject_class, property_id: PROP_DATABASE_ANCHORS, name: "anchors");
468}
469
470static void
471g_test_tls_database_init (GTestTlsDatabase *database)
472{
473}
474
475static gboolean
476g_test_tls_database_initable_init (GInitable *initable,
477 GCancellable *cancellable,
478 GError **error)
479{
480 return TRUE;
481}
482
483static void
484g_test_tls_file_database_file_database_interface_init (GInitableIface *iface)
485{
486}
487
488static void
489g_test_tls_database_initable_iface_init (GInitableIface *iface)
490{
491 iface->init = g_test_tls_database_initable_init;
492}
493

source code of gtk/subprojects/glib/gio/tests/gtesttlsbackend.c