1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 * GIO - GLib Input, Output and Streaming Library
5 * Copyright 2010 Red Hat, Inc
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see
19 * <http://www.gnu.org/licenses/>.
21 * In addition, when the library is used with OpenSSL, a special
22 * exception applies. Refer to the LICENSE_EXCEPTION file for details.
31 #include <gnutls/gnutls.h>
33 #include "gtlsbackend-gnutls.h"
34 #include "gtlscertificate-gnutls.h"
35 #include "gtlsclientconnection-gnutls.h"
36 #include "gtlsfiledatabase-gnutls.h"
37 #include "gtlsserverconnection-gnutls.h"
41 struct _GTlsBackendGnutls
43 GObject parent_instance;
46 GTlsDatabase *default_database;
49 static void g_tls_backend_gnutls_interface_init (GTlsBackendInterface *iface);
51 G_DEFINE_DYNAMIC_TYPE_EXTENDED (GTlsBackendGnutls, g_tls_backend_gnutls, G_TYPE_OBJECT, 0,
52 G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_TLS_BACKEND,
53 g_tls_backend_gnutls_interface_init);)
55 #ifdef GTLS_GNUTLS_DEBUG
57 gtls_log_func (int level, const char *msg)
59 #if ENABLE(TIZEN_DLOG)
60 TIZEN_LOGI("GTLS: %s", msg);
62 g_print ("GTLS: %s", msg);
68 gtls_gnutls_init (gpointer data)
72 gnutls_global_init ();
74 #ifdef GTLS_GNUTLS_DEBUG
75 gnutls_global_set_log_function (gtls_log_func);
76 gnutls_global_set_log_level (9);
79 /* Leak the module to keep it from being unloaded. */
80 plugin = g_type_get_plugin (G_TYPE_TLS_BACKEND_GNUTLS);
82 g_type_plugin_use (plugin);
86 GNUTLS_SKIP_GLOBAL_INIT
88 static GOnce gnutls_inited = G_ONCE_INIT;
91 g_tls_backend_gnutls_init (GTlsBackendGnutls *backend)
93 /* Once we call gtls_gnutls_init(), we can't allow the module to be
94 * unloaded (since if gnutls gets unloaded but gcrypt doesn't, then
95 * gcrypt will have dangling pointers to gnutls's mutex functions).
96 * So we initialize it from here rather than at class init time so
97 * that it doesn't happen unless the app is actually using TLS (as
98 * opposed to just calling g_io_modules_scan_all_in_directory()).
100 g_once (&gnutls_inited, gtls_gnutls_init, NULL);
102 g_mutex_init (&backend->mutex);
106 g_tls_backend_gnutls_finalize (GObject *object)
108 GTlsBackendGnutls *backend = G_TLS_BACKEND_GNUTLS (object);
110 g_clear_object (&backend->default_database);
111 g_mutex_clear (&backend->mutex);
113 G_OBJECT_CLASS (g_tls_backend_gnutls_parent_class)->finalize (object);
117 g_tls_backend_gnutls_class_init (GTlsBackendGnutlsClass *backend_class)
119 GObjectClass *gobject_class = G_OBJECT_CLASS (backend_class);
121 gobject_class->finalize = g_tls_backend_gnutls_finalize;
125 g_tls_backend_gnutls_class_finalize (GTlsBackendGnutlsClass *backend_class)
130 g_tls_backend_gnutls_get_default_database (GTlsBackend *backend)
132 GTlsBackendGnutls *self = G_TLS_BACKEND_GNUTLS (backend);
133 GTlsDatabase *result;
134 GError *error = NULL;
136 g_mutex_lock (&self->mutex);
138 if (self->default_database)
140 result = g_object_ref (self->default_database);
144 result = G_TLS_DATABASE (g_tls_database_gnutls_new (&error));
147 g_warning ("Failed to load TLS database: %s", error->message);
148 g_clear_error (&error);
153 self->default_database = g_object_ref (result);
157 g_mutex_unlock (&self->mutex);
163 g_tls_backend_gnutls_interface_init (GTlsBackendInterface *iface)
165 iface->get_certificate_type = g_tls_certificate_gnutls_get_type;
166 iface->get_client_connection_type = g_tls_client_connection_gnutls_get_type;
167 iface->get_server_connection_type = g_tls_server_connection_gnutls_get_type;
168 iface->get_file_database_type = g_tls_file_database_gnutls_get_type;
169 iface->get_default_database = g_tls_backend_gnutls_get_default_database;
170 iface->get_dtls_client_connection_type = g_tls_client_connection_gnutls_get_type;
171 iface->get_dtls_server_connection_type = g_tls_server_connection_gnutls_get_type;
174 /* Session cache support; all the details are sort of arbitrary. Note
175 * that having session_cache_cleanup() be a little bit slow isn't the
176 * end of the world, since it will still be faster than the network
177 * is. (NSS uses a linked list for its cache...)
180 G_LOCK_DEFINE_STATIC (session_cache_lock);
181 GHashTable *client_session_cache, *server_session_cache;
183 #define SESSION_CACHE_MAX_SIZE 50
184 #define SESSION_CACHE_MAX_AGE (60 * 60) /* one hour */
188 GBytes *session_data;
190 } GTlsBackendGnutlsCacheData;
193 session_cache_cleanup (GHashTable *cache)
197 GTlsBackendGnutlsCacheData *cache_data;
198 time_t expired = time (NULL) - SESSION_CACHE_MAX_AGE;
200 g_hash_table_iter_init (&iter, cache);
201 while (g_hash_table_iter_next (&iter, &key, &value))
204 if (cache_data->last_used < expired)
205 g_hash_table_iter_remove (&iter);
210 cache_data_free (gpointer data)
212 GTlsBackendGnutlsCacheData *cache_data = data;
214 g_bytes_unref (cache_data->session_id);
215 g_bytes_unref (cache_data->session_data);
220 get_session_cache (unsigned int type,
223 GHashTable **cache_p;
225 cache_p = (type == GNUTLS_CLIENT) ? &client_session_cache : &server_session_cache;
226 if (!*cache_p && create)
228 *cache_p = g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
229 NULL, cache_data_free);
235 g_tls_backend_gnutls_store_session (unsigned int type,
237 GBytes *session_data)
239 GTlsBackendGnutlsCacheData *cache_data;
242 G_LOCK (session_cache_lock);
244 cache = get_session_cache (type, TRUE);
245 cache_data = g_hash_table_lookup (cache, session_id);
248 if (!g_bytes_equal (cache_data->session_data, session_data))
250 g_bytes_unref (cache_data->session_data);
251 cache_data->session_data = g_bytes_ref (session_data);
256 if (g_hash_table_size (cache) >= SESSION_CACHE_MAX_SIZE)
257 session_cache_cleanup (cache);
259 cache_data = g_new (GTlsBackendGnutlsCacheData, 1);
260 cache_data->session_id = g_bytes_ref (session_id);
261 cache_data->session_data = g_bytes_ref (session_data);
263 g_hash_table_insert (cache, cache_data->session_id, cache_data);
265 cache_data->last_used = time (NULL);
267 G_UNLOCK (session_cache_lock);
271 g_tls_backend_gnutls_remove_session (unsigned int type,
276 G_LOCK (session_cache_lock);
278 cache = get_session_cache (type, FALSE);
280 g_hash_table_remove (cache, session_id);
282 G_UNLOCK (session_cache_lock);
286 g_tls_backend_gnutls_lookup_session (unsigned int type,
289 GTlsBackendGnutlsCacheData *cache_data;
290 GBytes *session_data = NULL;
293 G_LOCK (session_cache_lock);
295 cache = get_session_cache (type, FALSE);
298 cache_data = g_hash_table_lookup (cache, session_id);
301 cache_data->last_used = time (NULL);
302 session_data = g_bytes_ref (cache_data->session_data);
306 G_UNLOCK (session_cache_lock);
312 g_tls_backend_gnutls_register (GIOModule *module)
314 g_tls_backend_gnutls_register_type (G_TYPE_MODULE (module));
316 g_io_extension_point_register (G_TLS_BACKEND_EXTENSION_POINT_NAME);
317 g_io_extension_point_implement (G_TLS_BACKEND_EXTENSION_POINT_NAME,
318 g_tls_backend_gnutls_get_type(),