X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tls%2Fgnutls%2Fgtlsbackend-gnutls.c;h=d977e1b01fe0d31ffb4ea12e0631e17bd8a6a8bb;hb=refs%2Ftags%2Fsubmit%2Ftizen_6.0_hotfix%2F20201102.192901;hp=75b3e935dde30deb3ea1cb0d70150a23083f6b3e;hpb=e484f34fdd0d132acaedf0cbabc99708137e1293;p=platform%2Fupstream%2Fglib-networking.git diff --git a/tls/gnutls/gtlsbackend-gnutls.c b/tls/gnutls/gtlsbackend-gnutls.c index 75b3e93..d977e1b 100644 --- a/tls/gnutls/gtlsbackend-gnutls.c +++ b/tls/gnutls/gtlsbackend-gnutls.c @@ -1,11 +1,13 @@ -/* GIO - GLib Input, Output and Streaming Library +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * GIO - GLib Input, Output and Streaming Library * - * Copyright © 2010 Red Hat, Inc + * Copyright 2010 Red Hat, Inc * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -13,21 +15,20 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see + * . + * + * In addition, when the library is used with OpenSSL, a special + * exception applies. Refer to the LICENSE_EXCEPTION file for details. */ #include "config.h" #include "glib.h" #include +#include #include -#include -#ifndef G_OS_WIN32 -#include -#endif #include "gtlsbackend-gnutls.h" #include "gtlscertificate-gnutls.h" @@ -35,101 +36,66 @@ #include "gtlsfiledatabase-gnutls.h" #include "gtlsserverconnection-gnutls.h" -struct _GTlsBackendGnutlsPrivate +#include "TIZEN.h" + +struct _GTlsBackendGnutls { - GMutex *mutex; + GObject parent_instance; + + GMutex mutex; GTlsDatabase *default_database; }; static void g_tls_backend_gnutls_interface_init (GTlsBackendInterface *iface); G_DEFINE_DYNAMIC_TYPE_EXTENDED (GTlsBackendGnutls, g_tls_backend_gnutls, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_TLS_BACKEND, - g_tls_backend_gnutls_interface_init);) - -#if defined(GCRY_THREAD_OPTION_PTHREAD_IMPL) && !defined(G_OS_WIN32) -GCRY_THREAD_OPTION_PTHREAD_IMPL; -#endif + G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_TLS_BACKEND, + g_tls_backend_gnutls_interface_init);) -#ifdef G_OS_WIN32 - -static int -gtls_gcry_win32_mutex_init (void **priv) -{ - int err = 0; - CRITICAL_SECTION *lock = (CRITICAL_SECTION*)malloc (sizeof (CRITICAL_SECTION)); - - if (!lock) - err = ENOMEM; - if (!err) { - InitializeCriticalSection (lock); - *priv = lock; - } - return err; -} - -static int -gtls_gcry_win32_mutex_destroy (void **lock) -{ - DeleteCriticalSection ((CRITICAL_SECTION*)*lock); - free (*lock); - return 0; -} - -static int -gtls_gcry_win32_mutex_lock (void **lock) -{ - EnterCriticalSection ((CRITICAL_SECTION*)*lock); - return 0; -} - -static int -gtls_gcry_win32_mutex_unlock (void **lock) +#ifdef GTLS_GNUTLS_DEBUG +static void +gtls_log_func (int level, const char *msg) { - LeaveCriticalSection ((CRITICAL_SECTION*)*lock); - return 0; + g_print ("GTLS: %s", msg); } - - -static struct gcry_thread_cbs gtls_gcry_threads_win32 = { \ - (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)), \ - NULL, gtls_gcry_win32_mutex_init, gtls_gcry_win32_mutex_destroy, \ - gtls_gcry_win32_mutex_lock, gtls_gcry_win32_mutex_unlock, \ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - #endif static gpointer gtls_gnutls_init (gpointer data) { -#if defined(GCRY_THREAD_OPTION_PTHREAD_IMPL) && !defined(G_OS_WIN32) - gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); -#elif defined(G_OS_WIN32) - gcry_control (GCRYCTL_SET_THREAD_CBS, >ls_gcry_threads_win32); -#endif + GTypePlugin *plugin; + gnutls_global_init (); +#ifdef GTLS_GNUTLS_DEBUG + gnutls_global_set_log_function (gtls_log_func); + gnutls_global_set_log_level (9); +#endif + /* Leak the module to keep it from being unloaded. */ - g_type_plugin_use (g_type_get_plugin (G_TYPE_TLS_BACKEND_GNUTLS)); + plugin = g_type_get_plugin (G_TYPE_TLS_BACKEND_GNUTLS); + if (plugin != NULL) + g_type_plugin_use (plugin); return NULL; } +GNUTLS_SKIP_GLOBAL_INIT + static GOnce gnutls_inited = G_ONCE_INIT; static void g_tls_backend_gnutls_init (GTlsBackendGnutls *backend) { /* Once we call gtls_gnutls_init(), we can't allow the module to be - * unloaded, since that would break the pointers to the mutex - * functions we set for gcrypt. So we initialize it from here rather - * than at class init time so that it doesn't happen unless the app - * is actually using TLS (as opposed to just calling - * g_io_modules_scan_all_in_directory()). + * unloaded (since if gnutls gets unloaded but gcrypt doesn't, then + * gcrypt will have dangling pointers to gnutls's mutex functions). + * So we initialize it from here rather than at class init time so + * that it doesn't happen unless the app is actually using TLS (as + * opposed to just calling g_io_modules_scan_all_in_directory()). */ g_once (&gnutls_inited, gtls_gnutls_init, NULL); - backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (backend, G_TYPE_TLS_BACKEND_GNUTLS, GTlsBackendGnutlsPrivate); - backend->priv->mutex = g_mutex_new (); + g_mutex_init (&backend->mutex); } static void @@ -137,9 +103,8 @@ g_tls_backend_gnutls_finalize (GObject *object) { GTlsBackendGnutls *backend = G_TLS_BACKEND_GNUTLS (object); - if (backend->priv->default_database) - g_object_unref (backend->priv->default_database); - g_mutex_free (backend->priv->mutex); + g_clear_object (&backend->default_database); + g_mutex_clear (&backend->mutex); G_OBJECT_CLASS (g_tls_backend_gnutls_parent_class)->finalize (object); } @@ -148,8 +113,8 @@ static void g_tls_backend_gnutls_class_init (GTlsBackendGnutlsClass *backend_class) { GObjectClass *gobject_class = G_OBJECT_CLASS (backend_class); + gobject_class->finalize = g_tls_backend_gnutls_finalize; - g_type_class_add_private (backend_class, sizeof (GTlsBackendGnutlsPrivate)); } static void @@ -161,35 +126,31 @@ static GTlsDatabase* g_tls_backend_gnutls_get_default_database (GTlsBackend *backend) { GTlsBackendGnutls *self = G_TLS_BACKEND_GNUTLS (backend); - const gchar *anchor_file = NULL; GTlsDatabase *result; GError *error = NULL; - g_mutex_lock (self->priv->mutex); + g_mutex_lock (&self->mutex); - if (self->priv->default_database) + if (self->default_database) { - result = g_object_ref (self->priv->default_database); + result = g_object_ref (self->default_database); } else { -#ifdef GTLS_SYSTEM_CA_FILE - anchor_file = GTLS_SYSTEM_CA_FILE; -#endif - result = g_tls_file_database_new (anchor_file, &error); + result = G_TLS_DATABASE (g_tls_database_gnutls_new (&error)); if (error) { - g_warning ("couldn't load TLS file database: %s", - error->message); + g_warning ("Failed to load TLS database: %s", error->message); g_clear_error (&error); } else { - self->priv->default_database = g_object_ref (result); + g_assert (result); + self->default_database = g_object_ref (result); } } - g_mutex_unlock (self->priv->mutex); + g_mutex_unlock (&self->mutex); return result; } @@ -202,6 +163,8 @@ g_tls_backend_gnutls_interface_init (GTlsBackendInterface *iface) iface->get_server_connection_type = g_tls_server_connection_gnutls_get_type; iface->get_file_database_type = g_tls_file_database_gnutls_get_type; iface->get_default_database = g_tls_backend_gnutls_get_default_database; + iface->get_dtls_client_connection_type = g_tls_client_connection_gnutls_get_type; + iface->get_dtls_server_connection_type = g_tls_server_connection_gnutls_get_type; } /* Session cache support; all the details are sort of arbitrary. Note @@ -211,31 +174,31 @@ g_tls_backend_gnutls_interface_init (GTlsBackendInterface *iface) */ G_LOCK_DEFINE_STATIC (session_cache_lock); -GHashTable *session_cache; +GHashTable *client_session_cache, *server_session_cache; #define SESSION_CACHE_MAX_SIZE 50 #define SESSION_CACHE_MAX_AGE (60 * 60) /* one hour */ typedef struct { - gchar *session_id; - GByteArray *session_data; - time_t last_used; + GBytes *session_id; + GBytes *session_data; + time_t last_used; } GTlsBackendGnutlsCacheData; static void -session_cache_cleanup (void) +session_cache_cleanup (GHashTable *cache) { GHashTableIter iter; gpointer key, value; GTlsBackendGnutlsCacheData *cache_data; time_t expired = time (NULL) - SESSION_CACHE_MAX_AGE; - g_hash_table_iter_init (&iter, session_cache); + g_hash_table_iter_init (&iter, cache); while (g_hash_table_iter_next (&iter, &key, &value)) { cache_data = value; if (cache_data->last_used < expired) - g_hash_table_iter_remove (&iter); + g_hash_table_iter_remove (&iter); } } @@ -244,81 +207,98 @@ cache_data_free (gpointer data) { GTlsBackendGnutlsCacheData *cache_data = data; - g_free (cache_data->session_id); - g_byte_array_unref (cache_data->session_data); - g_slice_free (GTlsBackendGnutlsCacheData, cache_data); + g_bytes_unref (cache_data->session_id); + g_bytes_unref (cache_data->session_data); + g_free (cache_data); +} + +static GHashTable * +get_session_cache (unsigned int type, + gboolean create) +{ + GHashTable **cache_p; + + cache_p = (type == GNUTLS_CLIENT) ? &client_session_cache : &server_session_cache; + if (!*cache_p && create) + { + *cache_p = g_hash_table_new_full (g_bytes_hash, g_bytes_equal, + NULL, cache_data_free); + } + return *cache_p; } void -g_tls_backend_gnutls_cache_session_data (const gchar *session_id, - guchar *session_data, - gsize session_data_length) +g_tls_backend_gnutls_store_session (unsigned int type, + GBytes *session_id, + GBytes *session_data) { GTlsBackendGnutlsCacheData *cache_data; + GHashTable *cache; G_LOCK (session_cache_lock); - if (!session_cache) - session_cache = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, cache_data_free); - - cache_data = g_hash_table_lookup (session_cache, session_id); + cache = get_session_cache (type, TRUE); + cache_data = g_hash_table_lookup (cache, session_id); if (cache_data) { - if (cache_data->session_data->len == session_data_length && - memcmp (cache_data->session_data->data, - session_data, session_data_length) == 0) - { - cache_data->last_used = time (NULL); - G_UNLOCK (session_cache_lock); - return; - } - - g_byte_array_set_size (cache_data->session_data, 0); + if (!g_bytes_equal (cache_data->session_data, session_data)) + { + g_bytes_unref (cache_data->session_data); + cache_data->session_data = g_bytes_ref (session_data); + } } else { - if (g_hash_table_size (session_cache) >= SESSION_CACHE_MAX_SIZE) - session_cache_cleanup (); + if (g_hash_table_size (cache) >= SESSION_CACHE_MAX_SIZE) + session_cache_cleanup (cache); - cache_data = g_slice_new (GTlsBackendGnutlsCacheData); - cache_data->session_id = g_strdup (session_id); - cache_data->session_data = g_byte_array_sized_new (session_data_length); + cache_data = g_new (GTlsBackendGnutlsCacheData, 1); + cache_data->session_id = g_bytes_ref (session_id); + cache_data->session_data = g_bytes_ref (session_data); - g_hash_table_insert (session_cache, cache_data->session_id, cache_data); + g_hash_table_insert (cache, cache_data->session_id, cache_data); } - - g_byte_array_append (cache_data->session_data, - session_data, session_data_length); cache_data->last_used = time (NULL); + G_UNLOCK (session_cache_lock); } void -g_tls_backend_gnutls_uncache_session_data (const gchar *session_id) +g_tls_backend_gnutls_remove_session (unsigned int type, + GBytes *session_id) { + GHashTable *cache; + G_LOCK (session_cache_lock); - if (session_cache) - g_hash_table_remove (session_cache, session_id); + + cache = get_session_cache (type, FALSE); + if (cache) + g_hash_table_remove (cache, session_id); + G_UNLOCK (session_cache_lock); } -GByteArray * -g_tls_backend_gnutls_lookup_session_data (const gchar *session_id) +GBytes * +g_tls_backend_gnutls_lookup_session (unsigned int type, + GBytes *session_id) { GTlsBackendGnutlsCacheData *cache_data; - GByteArray *session_data = NULL; + GBytes *session_data = NULL; + GHashTable *cache; G_LOCK (session_cache_lock); - if (session_cache) + + cache = get_session_cache (type, FALSE); + if (cache) { - cache_data = g_hash_table_lookup (session_cache, session_id); + cache_data = g_hash_table_lookup (cache, session_id); if (cache_data) - { - cache_data->last_used = time (NULL); - session_data = g_byte_array_ref (cache_data->session_data); - } + { + cache_data->last_used = time (NULL); + session_data = g_bytes_ref (cache_data->session_data); + } } + G_UNLOCK (session_cache_lock); return session_data; @@ -328,8 +308,10 @@ void g_tls_backend_gnutls_register (GIOModule *module) { g_tls_backend_gnutls_register_type (G_TYPE_MODULE (module)); + if (module == NULL) + g_io_extension_point_register (G_TLS_BACKEND_EXTENSION_POINT_NAME); g_io_extension_point_implement (G_TLS_BACKEND_EXTENSION_POINT_NAME, - g_tls_backend_gnutls_get_type(), - "gnutls", - 0); + g_tls_backend_gnutls_get_type(), + "gnutls", + 0); }