• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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