X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tls%2Fgnutls%2Fgtlsdatabase-gnutls.c;h=eef1b1687c70e4e1fd8fd881bba7739c1d9be74b;hb=f032098bcb82432a475f0570b8b88ef40a7af777;hp=7704d561f872b74cd29aec6053aa7ee5dc23fe13;hpb=e1744c81348ca0414526096f3537d5725942abb1;p=platform%2Fupstream%2Fglib-networking.git diff --git a/tls/gnutls/gtlsdatabase-gnutls.c b/tls/gnutls/gtlsdatabase-gnutls.c index 7704d56..eef1b16 100644 --- a/tls/gnutls/gtlsdatabase-gnutls.c +++ b/tls/gnutls/gtlsdatabase-gnutls.c @@ -34,6 +34,8 @@ #include #include "gtlscertificate-gnutls.h" +#include "gtlshttp.h" +#include "gtlsgnutls-version.h" typedef struct { @@ -43,7 +45,7 @@ typedef struct */ GMutex mutex; - /* read-only after construct */ + /* Read-only after construct, but still has to be protected by the mutex. */ gnutls_x509_trust_list_t trust_list; /* @@ -92,7 +94,7 @@ bytes_multi_table_insert (GHashTable *table, GPtrArray *multi; multi = g_hash_table_lookup (table, key); - if (multi == NULL) + if (!multi) { multi = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref); g_hash_table_insert (table, g_bytes_ref (key), multi); @@ -107,7 +109,7 @@ bytes_multi_table_lookup_ref_one (GHashTable *table, GPtrArray *multi; multi = g_hash_table_lookup (table, key); - if (multi == NULL) + if (!multi) return NULL; g_assert (multi->len > 0); @@ -123,7 +125,7 @@ bytes_multi_table_lookup_ref_all (GHashTable *table, guint i; multi = g_hash_table_lookup (table, key); - if (multi == NULL) + if (!multi) return NULL; for (i = 0; i < multi->len; i++) @@ -149,7 +151,7 @@ create_handles_array_unlocked (GTlsDatabaseGnutls *self, { g_assert (G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate); handle = G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate (self, der); - if (handle != NULL) + if (handle) g_hash_table_insert (handles, handle, g_bytes_ref (der)); } @@ -170,7 +172,7 @@ initialize_tables (gnutls_x509_trust_list_t trust_list, GBytes *issuer = NULL; gint gerr; - while ((gerr = gnutls_x509_trust_list_iter_get_ca (trust_list, &iter, &cert)) == 0) + while (gnutls_x509_trust_list_iter_get_ca (trust_list, &iter, &cert) == 0) { gerr = gnutls_x509_crt_get_raw_dn (cert, &dn); if (gerr < 0) @@ -251,7 +253,7 @@ g_tls_database_gnutls_create_certificate_handle (GTlsDatabase *database, gchar *handle = NULL; der = g_tls_certificate_gnutls_get_bytes (G_TLS_CERTIFICATE_GNUTLS (certificate)); - g_return_val_if_fail (der != NULL, FALSE); + g_return_val_if_fail (der, FALSE); g_mutex_lock (&priv->mutex); @@ -299,12 +301,12 @@ g_tls_database_gnutls_lookup_certificate_for_handle (GTlsDatabase *d priv->handles = create_handles_array_unlocked (self, priv->complete); der = g_hash_table_lookup (priv->handles, handle); - if (der != NULL) + if (der) g_bytes_ref (der); g_mutex_unlock (&priv->mutex); - if (der == NULL) + if (!der) return NULL; datum.data = (unsigned char *)g_bytes_get_data (der, &length); @@ -367,14 +369,14 @@ g_tls_database_gnutls_lookup_certificate_issuer (GTlsDatabase *datab { issuer = NULL; } - else if (der != NULL) + else if (der) { datum.data = (unsigned char *)g_bytes_get_data (der, &length); datum.size = length; issuer = g_tls_certificate_gnutls_new (&datum, NULL); } - if (der != NULL) + if (der) g_bytes_unref (der); return issuer; } @@ -412,7 +414,7 @@ g_tls_database_gnutls_lookup_certificates_issued_by (GTlsDatabase *d g_bytes_unref (issuer); - for (l = ders; l != NULL; l = g_list_next (l)) + for (l = ders; l; l = g_list_next (l)) { if (g_cancellable_set_error_if_cancelled (cancellable, error)) { @@ -430,28 +432,44 @@ g_tls_database_gnutls_lookup_certificates_issued_by (GTlsDatabase *d return issued; } +typedef struct { + gnutls_x509_crt_t *chain; + guint length; +} CertificateChain; + +static CertificateChain * +certificate_chain_new (void) +{ + return g_new0 (CertificateChain, 1); +} + static void -convert_certificate_chain_to_gnutls (GTlsCertificateGnutls *chain, - gnutls_x509_crt_t **gnutls_chain, - guint *gnutls_chain_length) +certificate_chain_free (CertificateChain *chain) +{ + g_free (chain->chain); + g_free (chain); +} + +static CertificateChain * +convert_certificate_chain_to_gnutls (GTlsCertificateGnutls *chain) { GTlsCertificate *cert; - guint i; + CertificateChain *gnutls_chain; + guint i = 0; + + gnutls_chain = certificate_chain_new (); - g_assert (gnutls_chain); - g_assert (gnutls_chain_length); + for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert)) + gnutls_chain->length++; - for (*gnutls_chain_length = 0, cert = G_TLS_CERTIFICATE (chain); - cert; cert = g_tls_certificate_get_issuer (cert)) - ++(*gnutls_chain_length); + gnutls_chain->chain = g_new (gnutls_x509_crt_t, gnutls_chain->length); - *gnutls_chain = g_new0 (gnutls_x509_crt_t, *gnutls_chain_length); + for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert), i++) + gnutls_chain->chain[i] = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (cert)); - for (i = 0, cert = G_TLS_CERTIFICATE (chain); - cert; cert = g_tls_certificate_get_issuer (cert), ++i) - (*gnutls_chain)[i] = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (cert)); + g_assert (i == gnutls_chain->length); - g_assert (i == *gnutls_chain_length); + return gnutls_chain; } static GTlsCertificateFlags @@ -468,10 +486,7 @@ g_tls_database_gnutls_verify_chain (GTlsDatabase *database, GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self); GTlsCertificateFlags result; guint gnutls_result; - gnutls_x509_crt_t *certs; - guint certs_length; - const char *hostname = NULL; - char *free_hostname = NULL; + CertificateChain *gnutls_chain; int gerr; g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (chain), @@ -481,39 +496,27 @@ g_tls_database_gnutls_verify_chain (GTlsDatabase *database, if (g_cancellable_set_error_if_cancelled (cancellable, error)) return G_TLS_CERTIFICATE_GENERIC_ERROR; - convert_certificate_chain_to_gnutls (G_TLS_CERTIFICATE_GNUTLS (chain), - &certs, &certs_length); + g_mutex_lock (&priv->mutex); + gnutls_chain = convert_certificate_chain_to_gnutls (G_TLS_CERTIFICATE_GNUTLS (chain)); gerr = gnutls_x509_trust_list_verify_crt (priv->trust_list, - certs, certs_length, + gnutls_chain->chain, gnutls_chain->length, 0, &gnutls_result, NULL); + g_mutex_unlock (&priv->mutex); if (gerr != 0 || g_cancellable_set_error_if_cancelled (cancellable, error)) { - g_free (certs); + certificate_chain_free (gnutls_chain); return G_TLS_CERTIFICATE_GENERIC_ERROR; } result = g_tls_certificate_gnutls_convert_flags (gnutls_result); - if (G_IS_NETWORK_ADDRESS (identity)) - hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity)); - else if (G_IS_NETWORK_SERVICE (identity)) - hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity)); - else if (G_IS_INET_SOCKET_ADDRESS (identity)) - { - GInetAddress *addr; + if (identity) + result |= g_tls_certificate_gnutls_verify_identity (G_TLS_CERTIFICATE_GNUTLS (chain), + identity, + error); - addr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (identity)); - hostname = free_hostname = g_inet_address_to_string (addr); - } - if (hostname) - { - if (!gnutls_x509_crt_check_hostname (certs[0], hostname)) - result |= G_TLS_CERTIFICATE_BAD_IDENTITY; - g_free (free_hostname); - } - - g_free (certs); + certificate_chain_free (gnutls_chain); return result; } @@ -561,6 +564,57 @@ g_tls_database_gnutls_populate_trust_list (GTlsDatabaseGnutls *self, return gerr >= 0; } +static gnutls_x509_trust_list_t +create_trust_list (GTlsDatabaseGnutls *self, + GError **error) +{ + GTlsDatabaseGnutlsClass *database_class = G_TLS_DATABASE_GNUTLS_GET_CLASS (self); + gnutls_x509_trust_list_t trust_list; + int ret; + + ret = gnutls_x509_trust_list_init (&trust_list, 0); + if (ret != 0) + { + g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC, "Failed to initialize trust list: %s", gnutls_strerror (ret)); + return NULL; + } + + g_assert (database_class->populate_trust_list); + if (!database_class->populate_trust_list (self, trust_list, error)) + { + gnutls_x509_trust_list_deinit (trust_list, TRUE); + return NULL; + } + + return trust_list; +} + +gnutls_certificate_credentials_t +g_tls_database_gnutls_get_credentials (GTlsDatabaseGnutls *self, + GError **error) +{ + gnutls_certificate_credentials_t credentials; + gnutls_x509_trust_list_t trust_list = NULL; + int ret; + + ret = gnutls_certificate_allocate_credentials (&credentials); + if (ret != 0) + { + g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC, "Failed to allocate credentials: %s", gnutls_strerror (ret)); + return NULL; + } + + trust_list = create_trust_list (self, error); + if (!trust_list) + { + gnutls_certificate_free_credentials (credentials); + return NULL; + } + + gnutls_certificate_set_trust_list (credentials, trust_list, 0); + return credentials; +} + static void g_tls_database_gnutls_class_init (GTlsDatabaseGnutlsClass *klass) { @@ -595,14 +649,9 @@ g_tls_database_gnutls_initable_init (GInitable *initable, if (g_cancellable_set_error_if_cancelled (cancellable, error)) return FALSE; - gnutls_x509_trust_list_init (&trust_list, 0); - - g_assert (G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->populate_trust_list); - if (!G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->populate_trust_list (self, trust_list, error)) - { - result = FALSE; - goto out; - } + trust_list = create_trust_list (self, error); + if (!trust_list) + return FALSE; subjects = bytes_multi_table_new (); issuers = bytes_multi_table_new (); @@ -642,14 +691,13 @@ g_tls_database_gnutls_initable_init (GInitable *initable, g_mutex_unlock (&priv->mutex); } -out: - if (trust_list != NULL) + if (trust_list) gnutls_x509_trust_list_deinit (trust_list, 1); - if (subjects != NULL) + if (subjects) g_hash_table_unref (subjects); - if (issuers != NULL) + if (issuers) g_hash_table_unref (issuers); - if (complete != NULL) + if (complete) g_hash_table_unref (complete); return result; }