[glib-networking/verify-paths: 1/4] database: use the default system store provided by openssl
- From: Ignacio Casal Quinteiro <icq src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/verify-paths: 1/4] database: use the default system store provided by openssl
- Date: Thu, 25 Apr 2019 10:18:27 +0000 (UTC)
commit a40a1a181b3fe4eaeae2e451633a06b4a00d6032
Author: Ignacio Casal Quinteiro <qignacio amazon com>
Date: Thu Apr 25 11:11:40 2019 +0200
database: use the default system store provided by openssl
And let the file database an independent class in case that we
need to use it.
Note the default database does not implement all the base class
methods since openssl does not provide us the api to iterate
over the ca certificates.
This is the reason the file database stays as is so we can iterate
over and have good unit tests. In theory for the file database
we should just add the file to the store and be done with it.
tls/openssl/gtlsbackend-openssl.c | 40 +---
tls/openssl/gtlsbackend-openssl.h | 3 -
tls/openssl/gtlsconnection-openssl.c | 8 +-
tls/openssl/gtlsdatabase-openssl.c | 331 ++++++++++++++++++++++++++++++-
tls/openssl/gtlsdatabase-openssl.h | 26 +--
tls/openssl/gtlsfiledatabase-openssl.c | 343 +++------------------------------
tls/openssl/gtlsfiledatabase-openssl.h | 4 -
7 files changed, 372 insertions(+), 383 deletions(-)
---
diff --git a/tls/openssl/gtlsbackend-openssl.c b/tls/openssl/gtlsbackend-openssl.c
index abff7bb..611aaca 100644
--- a/tls/openssl/gtlsbackend-openssl.c
+++ b/tls/openssl/gtlsbackend-openssl.c
@@ -189,49 +189,12 @@ g_tls_backend_openssl_finalize (GObject *object)
G_OBJECT_CLASS (g_tls_backend_openssl_parent_class)->finalize (object);
}
-static GTlsDatabase *
-g_tls_backend_openssl_real_create_database (GTlsBackendOpenssl *self,
- GError **error)
-{
- gchar *anchor_file = NULL;
- GTlsDatabase *database;
-
-#ifdef G_OS_WIN32
- if (g_getenv ("G_TLS_OPENSSL_HANDLE_CERT_RELOCATABLE") != NULL)
- {
- gchar *module_dir;
-
- module_dir = g_win32_get_package_installation_directory_of_module (NULL);
- anchor_file = g_build_filename (module_dir, "bin", "cert.pem", NULL);
- g_free (module_dir);
- }
-#endif
-
- if (anchor_file == NULL)
- {
- const gchar *openssl_cert_file;
-
- openssl_cert_file = g_getenv (X509_get_default_cert_file_env ());
- if (openssl_cert_file == NULL)
- openssl_cert_file = X509_get_default_cert_file ();
-
- anchor_file = g_strdup (openssl_cert_file);
- }
-
- database = g_tls_file_database_new (anchor_file, error);
- g_free (anchor_file);
-
- return database;
-}
-
static void
g_tls_backend_openssl_class_init (GTlsBackendOpensslClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = g_tls_backend_openssl_finalize;
-
- klass->create_database = g_tls_backend_openssl_real_create_database;
}
static void
@@ -257,8 +220,7 @@ g_tls_backend_openssl_get_default_database (GTlsBackend *backend)
}
else
{
- g_assert (G_TLS_BACKEND_OPENSSL_GET_CLASS (openssl_backend)->create_database);
- result = G_TLS_BACKEND_OPENSSL_GET_CLASS (openssl_backend)->create_database (openssl_backend, &error);
+ result = G_TLS_DATABASE (g_tls_database_openssl_new (&error));
if (error)
{
g_warning ("Couldn't load TLS file database: %s",
diff --git a/tls/openssl/gtlsbackend-openssl.h b/tls/openssl/gtlsbackend-openssl.h
index 410b0fb..d920673 100644
--- a/tls/openssl/gtlsbackend-openssl.h
+++ b/tls/openssl/gtlsbackend-openssl.h
@@ -36,9 +36,6 @@ G_DECLARE_DERIVABLE_TYPE (GTlsBackendOpenssl, g_tls_backend_openssl,
struct _GTlsBackendOpensslClass
{
GObjectClass parent_class;
-
- GTlsDatabase* (*create_database) (GTlsBackendOpenssl *backend,
- GError **error);
};
void g_tls_backend_openssl_register (GIOModule *module);
diff --git a/tls/openssl/gtlsconnection-openssl.c b/tls/openssl/gtlsconnection-openssl.c
index c6df559..27f4dbc 100644
--- a/tls/openssl/gtlsconnection-openssl.c
+++ b/tls/openssl/gtlsconnection-openssl.c
@@ -32,7 +32,7 @@
#include "gtlsconnection-openssl.h"
#include "gtlsbackend-openssl.h"
#include "gtlscertificate-openssl.h"
-#include "gtlsfiledatabase-openssl.h"
+#include "gtlsdatabase-openssl.h"
#include "gtlsbio.h"
#include <glib/gi18n-lib.h>
@@ -300,9 +300,9 @@ verify_ocsp_response (GTlsConnectionOpenssl *openssl,
if (resp == NULL)
return G_TLS_CERTIFICATE_GENERIC_ERROR;
- return g_tls_file_database_openssl_verify_ocsp_response (database,
- peer_certificate,
- resp);
+ return g_tls_database_openssl_verify_ocsp_response (G_TLS_DATABASE_OPENSSL (database),
+ peer_certificate,
+ resp);
#else
return 0;
#endif
diff --git a/tls/openssl/gtlsdatabase-openssl.c b/tls/openssl/gtlsdatabase-openssl.c
index 93461a2..34576aa 100644
--- a/tls/openssl/gtlsdatabase-openssl.c
+++ b/tls/openssl/gtlsdatabase-openssl.c
@@ -1,5 +1,5 @@
/*
- * gtlsdatabase-openssl.c
+ * gtlsfiledatabase-openssl.c
*
* Copyright (C) 2015 NICE s.r.l.
*
@@ -26,14 +26,339 @@
#include "gtlsdatabase-openssl.h"
-G_DEFINE_ABSTRACT_TYPE (GTlsDatabaseOpenssl, g_tls_database_openssl, G_TYPE_TLS_DATABASE)
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+#include "openssl-include.h"
+
+typedef struct _GTlsDatabaseOpensslPrivate
+{
+ /*
+ * This class is protected by mutex because the default GTlsDatabase
+ * is a global singleton, accessible via the default GTlsBackend.
+ */
+ GMutex mutex;
+
+ /* read-only after construct */
+ X509_STORE *store;
+} GTlsDatabaseOpensslPrivate;
+
+static void g_tls_database_openssl_initable_interface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GTlsDatabaseOpenssl, g_tls_database_openssl, G_TYPE_TLS_DATABASE,
+ G_ADD_PRIVATE (GTlsDatabaseOpenssl)
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ g_tls_database_openssl_initable_interface_init))
+
+static void
+g_tls_database_openssl_finalize (GObject *object)
+{
+ GTlsDatabaseOpenssl *self = G_TLS_DATABASE_OPENSSL (object);
+ GTlsDatabaseOpensslPrivate *priv;
+
+ priv = g_tls_database_openssl_get_instance_private (self);
+
+ if (priv->store != NULL)
+ X509_STORE_free (priv->store);
+
+ g_mutex_clear (&priv->mutex);
+
+ G_OBJECT_CLASS (g_tls_database_openssl_parent_class)->finalize (object);
+}
+
+static void
+g_tls_database_openssl_init (GTlsDatabaseOpenssl *self)
+{
+ GTlsDatabaseOpensslPrivate *priv;
+
+ priv = g_tls_database_openssl_get_instance_private (self);
+
+ g_mutex_init (&priv->mutex);
+}
+
+static GTlsCertificateFlags
+double_check_before_after_dates (GTlsCertificateOpenssl *chain)
+{
+ GTlsCertificateFlags gtls_flags = 0;
+ X509 *cert;
+
+ while (chain)
+ {
+ ASN1_TIME *not_before;
+ ASN1_TIME *not_after;
+
+ cert = g_tls_certificate_openssl_get_cert (chain);
+ not_before = X509_get_notBefore (cert);
+ not_after = X509_get_notAfter (cert);
+
+ if (X509_cmp_current_time (not_before) > 0)
+ gtls_flags |= G_TLS_CERTIFICATE_NOT_ACTIVATED;
+
+ if (X509_cmp_current_time (not_after) < 0)
+ gtls_flags |= G_TLS_CERTIFICATE_EXPIRED;
+
+ chain = G_TLS_CERTIFICATE_OPENSSL (g_tls_certificate_get_issuer
+ (G_TLS_CERTIFICATE (chain)));
+ }
+
+ return gtls_flags;
+}
+
+static STACK_OF(X509) *
+convert_certificate_chain_to_openssl (GTlsCertificateOpenssl *chain)
+{
+ GTlsCertificate *cert;
+ STACK_OF(X509) *openssl_chain;
+
+ openssl_chain = sk_X509_new_null ();
+
+ for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert))
+ sk_X509_push (openssl_chain, g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (cert)));
+
+ return openssl_chain;
+}
+
+static GTlsCertificateFlags
+g_tls_database_openssl_verify_chain (GTlsDatabase *database,
+ GTlsCertificate *chain,
+ const gchar *purpose,
+ GSocketConnectable *identity,
+ GTlsInteraction *interaction,
+ GTlsDatabaseVerifyFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsDatabaseOpenssl *self = G_TLS_DATABASE_OPENSSL (database);
+ GTlsDatabaseOpensslPrivate *priv;
+ STACK_OF(X509) *certs;
+ X509_STORE_CTX *csc;
+ X509 *x;
+ GTlsCertificateFlags result = 0;
+
+ g_return_val_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (chain),
+ G_TLS_CERTIFICATE_GENERIC_ERROR);
+
+ priv = g_tls_database_openssl_get_instance_private (self);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return G_TLS_CERTIFICATE_GENERIC_ERROR;
+
+ certs = convert_certificate_chain_to_openssl (G_TLS_CERTIFICATE_OPENSSL (chain));
+
+ csc = X509_STORE_CTX_new ();
+
+ x = g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (chain));
+ if (!X509_STORE_CTX_init (csc, priv->store, x, certs))
+ {
+ X509_STORE_CTX_free (csc);
+ sk_X509_free (certs);
+ return G_TLS_CERTIFICATE_GENERIC_ERROR;
+ }
+
+ if (X509_verify_cert (csc) <= 0)
+ result = g_tls_certificate_openssl_convert_error (X509_STORE_CTX_get_error (csc));
+
+ X509_STORE_CTX_free (csc);
+ sk_X509_free (certs);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return G_TLS_CERTIFICATE_GENERIC_ERROR;
+
+ /* We have to check these ourselves since openssl
+ * does not give us flags and UNKNOWN_CA will take priority.
+ */
+ result |= double_check_before_after_dates (G_TLS_CERTIFICATE_OPENSSL (chain));
+
+ if (identity)
+ result |= g_tls_certificate_openssl_verify_identity (G_TLS_CERTIFICATE_OPENSSL (chain),
+ identity);
+
+ return result;
+}
+
+static gboolean
+g_tls_database_openssl_populate_trust_list (GTlsDatabaseOpenssl *self,
+ X509_STORE *store,
+ GError **error)
+{
+ if (!X509_STORE_set_default_paths (store))
+ {
+ g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ _("Failed to load system trust store: %s"),
+ ERR_error_string (ERR_get_error (), NULL));
+ return FALSE;
+ }
+
+ return TRUE;
+}
static void
g_tls_database_openssl_class_init (GTlsDatabaseOpensslClass *klass)
{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GTlsDatabaseClass *database_class = G_TLS_DATABASE_CLASS (klass);
+
+ gobject_class->finalize = g_tls_database_openssl_finalize;
+
+ database_class->verify_chain = g_tls_database_openssl_verify_chain;
+
+ klass->populate_trust_list = g_tls_database_openssl_populate_trust_list;
+}
+
+static gboolean
+g_tls_database_openssl_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsDatabaseOpenssl *self = G_TLS_DATABASE_OPENSSL (initable);
+ GTlsDatabaseOpensslPrivate *priv;
+ X509_STORE *store;
+ gboolean result;
+
+ priv = g_tls_database_openssl_get_instance_private (self);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return FALSE;
+
+ store = X509_STORE_new ();
+ if (store == NULL)
+ {
+ g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ _("Could not create CA store"));
+ result = FALSE;
+ goto out;
+ }
+
+ g_assert (G_TLS_DATABASE_OPENSSL_GET_CLASS (self)->populate_trust_list);
+ if (!G_TLS_DATABASE_OPENSSL_GET_CLASS (self)->populate_trust_list (self, store, error))
+ {
+ result = FALSE;
+ goto out;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ result = FALSE;
+
+ if (result)
+ {
+ g_mutex_lock (&priv->mutex);
+ if (!priv->store)
+ {
+ priv->store = store;
+ store = NULL;
+ }
+ g_mutex_unlock (&priv->mutex);
+ }
+
+out:
+ if (store != NULL)
+ X509_STORE_free (store);
+
+ return result;
}
static void
-g_tls_database_openssl_init (GTlsDatabaseOpenssl *openssl)
+g_tls_database_openssl_initable_interface_init (GInitableIface *iface)
+{
+ iface->init = g_tls_database_openssl_initable_init;
+}
+
+GTlsDatabaseOpenssl *
+g_tls_database_openssl_new (GError **error)
{
+ g_return_val_if_fail (!error || !*error, NULL);
+
+ return g_initable_new (G_TYPE_TLS_DATABASE_OPENSSL, NULL, error, NULL);
+}
+
+GTlsCertificateFlags
+g_tls_database_openssl_verify_ocsp_response (GTlsDatabaseOpenssl *self,
+ GTlsCertificate *chain,
+ OCSP_RESPONSE *resp)
+{
+ GTlsCertificateFlags errors = 0;
+#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
+ !defined(OPENSSL_NO_OCSP)
+ GTlsDatabaseOpensslPrivate *priv;
+ STACK_OF(X509) *chain_openssl = NULL;
+ OCSP_BASICRESP *basic_resp = NULL;
+ int ocsp_status = 0;
+ int i;
+
+ ocsp_status = OCSP_response_status (resp);
+ if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL)
+ {
+ errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
+ goto end;
+ }
+
+ basic_resp = OCSP_response_get1_basic (resp);
+ if (basic_resp == NULL)
+ {
+ errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
+ goto end;
+ }
+
+ chain_openssl = convert_certificate_chain_to_openssl (G_TLS_CERTIFICATE_OPENSSL (chain));
+ priv = g_tls_database_openssl_get_instance_private (self);
+ if ((chain_openssl == NULL) ||
+ (priv->store == NULL))
+ {
+ errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
+ goto end;
+ }
+
+ if (OCSP_basic_verify (basic_resp, chain_openssl, priv->store, 0) <= 0)
+ {
+ errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
+ goto end;
+ }
+
+ for (i = 0; i < OCSP_resp_count (basic_resp); i++)
+ {
+ OCSP_SINGLERESP *single_resp = OCSP_resp_get0 (basic_resp, i);
+ ASN1_GENERALIZEDTIME *revocation_time = NULL;
+ ASN1_GENERALIZEDTIME *this_update_time = NULL;
+ ASN1_GENERALIZEDTIME *next_update_time = NULL;
+ int crl_reason = 0;
+ int cert_status = 0;
+
+ if (single_resp == NULL)
+ continue;
+
+ cert_status = OCSP_single_get0_status (single_resp,
+ &crl_reason,
+ &revocation_time,
+ &this_update_time,
+ &next_update_time);
+ if (!OCSP_check_validity (this_update_time,
+ next_update_time,
+ 300L,
+ -1L))
+ {
+ errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
+ goto end;
+ }
+
+ switch (cert_status)
+ {
+ case V_OCSP_CERTSTATUS_GOOD:
+ break;
+ case V_OCSP_CERTSTATUS_REVOKED:
+ errors = G_TLS_CERTIFICATE_REVOKED;
+ goto end;
+ case V_OCSP_CERTSTATUS_UNKNOWN:
+ errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
+ goto end;
+ }
+ }
+
+end:
+ if (basic_resp != NULL)
+ OCSP_BASICRESP_free (basic_resp);
+
+ if (resp != NULL)
+ OCSP_RESPONSE_free (resp);
+
+#endif
+ return errors;
}
diff --git a/tls/openssl/gtlsdatabase-openssl.h b/tls/openssl/gtlsdatabase-openssl.h
index fd31352..ffd8778 100644
--- a/tls/openssl/gtlsdatabase-openssl.h
+++ b/tls/openssl/gtlsdatabase-openssl.h
@@ -31,32 +31,24 @@
G_BEGIN_DECLS
-typedef enum {
- G_TLS_DATABASE_OPENSSL_PINNED_CERTIFICATE = 1,
- G_TLS_DATABASE_OPENSSL_ANCHORED_CERTIFICATE = 2,
-} GTlsDatabaseOpensslAssertion;
-
#define G_TYPE_TLS_DATABASE_OPENSSL (g_tls_database_openssl_get_type ())
-#define G_TLS_DATABASE_OPENSSL(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst),
G_TYPE_TLS_DATABASE_OPENSSL, GTlsDatabaseOpenssl))
-#define G_TLS_DATABASE_OPENSSL_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class),
G_TYPE_TLS_DATABASE_OPENSSL, GTlsDatabaseOpensslClass))
-#define G_IS_TLS_DATABASE_OPENSSL(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst),
G_TYPE_TLS_DATABASE_OPENSSL))
-#define G_IS_TLS_DATABASE_OPENSSL_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class),
G_TYPE_TLS_DATABASE_OPENSSL))
-#define G_TLS_DATABASE_OPENSSL_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst),
G_TYPE_TLS_DATABASE_OPENSSL, GTlsDatabaseOpensslClass))
-typedef struct _GTlsDatabaseOpensslClass GTlsDatabaseOpensslClass;
-typedef struct _GTlsDatabaseOpenssl GTlsDatabaseOpenssl;
+G_DECLARE_DERIVABLE_TYPE (GTlsDatabaseOpenssl, g_tls_database_openssl, G, TLS_DATABASE_OPENSSL, GTlsDatabase)
struct _GTlsDatabaseOpensslClass
{
GTlsDatabaseClass parent_class;
-};
-struct _GTlsDatabaseOpenssl
-{
- GTlsDatabase parent_instance;
+ gboolean (*populate_trust_list) (GTlsDatabaseOpenssl *self,
+ X509_STORE *store,
+ GError **error);
};
-GType g_tls_database_openssl_get_type (void) G_GNUC_CONST;
+GTlsDatabaseOpenssl *g_tls_database_openssl_new (GError **error);
+
+GTlsCertificateFlags g_tls_database_openssl_verify_ocsp_response (GTlsDatabaseOpenssl *self,
+ GTlsCertificate *chain,
+ OCSP_RESPONSE *resp);
G_END_DECLS
diff --git a/tls/openssl/gtlsfiledatabase-openssl.c b/tls/openssl/gtlsfiledatabase-openssl.c
index e45a619..7ea58e1 100644
--- a/tls/openssl/gtlsfiledatabase-openssl.c
+++ b/tls/openssl/gtlsfiledatabase-openssl.c
@@ -34,7 +34,6 @@ typedef struct _GTlsFileDatabaseOpensslPrivate
{
/* read-only after construct */
gchar *anchor_filename;
- STACK_OF(X509) *trusted;
/* protected by mutex */
GMutex mutex;
@@ -75,14 +74,11 @@ enum
static void g_tls_file_database_openssl_file_database_interface_init (GTlsFileDatabaseInterface *iface);
-static void g_tls_file_database_openssl_initable_interface_init (GInitableIface *iface);
-
G_DEFINE_TYPE_WITH_CODE (GTlsFileDatabaseOpenssl, g_tls_file_database_openssl, G_TYPE_TLS_DATABASE_OPENSSL,
G_ADD_PRIVATE (GTlsFileDatabaseOpenssl)
G_IMPLEMENT_INTERFACE (G_TYPE_TLS_FILE_DATABASE,
g_tls_file_database_openssl_file_database_interface_init)
- G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
- g_tls_file_database_openssl_initable_interface_init))
+ )
static GHashTable *
bytes_multi_table_new (void)
@@ -242,9 +238,6 @@ g_tls_file_database_openssl_finalize (GObject *object)
g_free (priv->anchor_filename);
priv->anchor_filename = NULL;
- if (priv->trusted != NULL)
- sk_X509_pop_free (priv->trusted, X509_free);
-
g_mutex_clear (&priv->mutex);
G_OBJECT_CLASS (g_tls_file_database_openssl_parent_class)->finalize (object);
@@ -271,54 +264,6 @@ g_tls_file_database_openssl_get_property (GObject *object,
}
}
-static STACK_OF(X509) *
-load_certs (const gchar *file_name)
-{
- BIO *bio;
- STACK_OF(X509) *certs;
- STACK_OF(X509_INFO) *xis = NULL;
- gint i;
-
- if (file_name == NULL)
- return NULL;
-
- bio = BIO_new_file (file_name, "rb");
- if (bio == NULL)
- return NULL;
-
- xis = PEM_X509_INFO_read_bio (bio, NULL, NULL, NULL);
-
- BIO_free (bio);
-
- certs = sk_X509_new_null ();
- if (certs == NULL)
- goto end;
-
- for (i = 0; i < sk_X509_INFO_num (xis); i++)
- {
- X509_INFO *xi;
-
- xi = sk_X509_INFO_value (xis, i);
- if (xi->x509 != NULL)
- {
- if (!sk_X509_push (certs, xi->x509))
- goto end;
- xi->x509 = NULL;
- }
- }
-
-end:
- sk_X509_INFO_pop_free (xis, X509_INFO_free);
-
- if (sk_X509_num (certs) == 0)
- {
- sk_X509_pop_free (certs, X509_free);
- certs = NULL;
- }
-
- return certs;
-}
-
static void
g_tls_file_database_openssl_set_property (GObject *object,
guint prop_id,
@@ -342,15 +287,8 @@ g_tls_file_database_openssl_set_property (GObject *object,
return;
}
- if (priv->anchor_filename)
- {
- g_free (priv->anchor_filename);
- if (priv->trusted != NULL)
- sk_X509_pop_free (priv->trusted, X509_free);
- }
-
+ g_free (priv->anchor_filename);
priv->anchor_filename = g_strdup (anchor_path);
- priv->trusted = load_certs (anchor_path);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -527,155 +465,25 @@ g_tls_file_database_openssl_lookup_certificates_issued_by (GTlsDatabase
return issued;
}
-static GTlsCertificateFlags
-double_check_before_after_dates (GTlsCertificateOpenssl *chain)
-{
- GTlsCertificateFlags gtls_flags = 0;
- X509 *cert;
-
- while (chain)
- {
- ASN1_TIME *not_before;
- ASN1_TIME *not_after;
-
- cert = g_tls_certificate_openssl_get_cert (chain);
- not_before = X509_get_notBefore (cert);
- not_after = X509_get_notAfter (cert);
-
- if (X509_cmp_current_time (not_before) > 0)
- gtls_flags |= G_TLS_CERTIFICATE_NOT_ACTIVATED;
-
- if (X509_cmp_current_time (not_after) < 0)
- gtls_flags |= G_TLS_CERTIFICATE_EXPIRED;
-
- chain = G_TLS_CERTIFICATE_OPENSSL (g_tls_certificate_get_issuer
- (G_TLS_CERTIFICATE (chain)));
- }
-
- return gtls_flags;
-}
-
-static STACK_OF(X509) *
-convert_certificate_chain_to_openssl (GTlsCertificateOpenssl *chain)
-{
- GTlsCertificate *cert;
- STACK_OF(X509) *openssl_chain;
-
- openssl_chain = sk_X509_new_null ();
-
- for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert))
- sk_X509_push (openssl_chain, g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (cert)));
-
- return openssl_chain;
-}
-
-static GTlsCertificateFlags
-g_tls_file_database_openssl_verify_chain (GTlsDatabase *database,
- GTlsCertificate *chain,
- const gchar *purpose,
- GSocketConnectable *identity,
- GTlsInteraction *interaction,
- GTlsDatabaseVerifyFlags flags,
- GCancellable *cancellable,
- GError **error)
-{
- GTlsFileDatabaseOpenssl *file_database;
- GTlsFileDatabaseOpensslPrivate *priv;
- STACK_OF(X509) *certs;
- X509_STORE *store;
- X509_STORE_CTX *csc;
- X509 *x;
- GTlsCertificateFlags result = 0;
-
- g_return_val_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (chain),
- G_TLS_CERTIFICATE_GENERIC_ERROR);
-
- file_database = G_TLS_FILE_DATABASE_OPENSSL (database);
-
- priv = g_tls_file_database_openssl_get_instance_private (file_database);
-
- if (g_cancellable_set_error_if_cancelled (cancellable, error))
- return G_TLS_CERTIFICATE_GENERIC_ERROR;
-
- certs = convert_certificate_chain_to_openssl (G_TLS_CERTIFICATE_OPENSSL (chain));
-
- store = X509_STORE_new ();
- csc = X509_STORE_CTX_new ();
-
- x = g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (chain));
- if (!X509_STORE_CTX_init (csc, store, x, certs))
- {
- X509_STORE_CTX_free (csc);
- X509_STORE_free (store);
- sk_X509_free (certs);
- return G_TLS_CERTIFICATE_GENERIC_ERROR;
- }
-
- if (priv->trusted)
- {
- X509_STORE_CTX_trusted_stack (csc, priv->trusted);
- }
-
- if (X509_verify_cert (csc) <= 0)
- result = g_tls_certificate_openssl_convert_error (X509_STORE_CTX_get_error (csc));
-
- X509_STORE_CTX_free (csc);
- X509_STORE_free (store);
- sk_X509_free (certs);
-
- if (g_cancellable_set_error_if_cancelled (cancellable, error))
- return G_TLS_CERTIFICATE_GENERIC_ERROR;
-
- /* We have to check these ourselves since openssl
- * does not give us flags and UNKNOWN_CA will take priority.
- */
- result |= double_check_before_after_dates (G_TLS_CERTIFICATE_OPENSSL (chain));
-
- if (identity)
- result |= g_tls_certificate_openssl_verify_identity (G_TLS_CERTIFICATE_OPENSSL (chain),
- identity);
-
- return result;
-}
-
-static void
-g_tls_file_database_openssl_class_init (GTlsFileDatabaseOpensslClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GTlsDatabaseClass *database_class = G_TLS_DATABASE_CLASS (klass);
-
- gobject_class->get_property = g_tls_file_database_openssl_get_property;
- gobject_class->set_property = g_tls_file_database_openssl_set_property;
- gobject_class->finalize = g_tls_file_database_openssl_finalize;
-
- database_class->create_certificate_handle = g_tls_file_database_openssl_create_certificate_handle;
- database_class->lookup_certificate_for_handle = g_tls_file_database_openssl_lookup_certificate_for_handle;
- database_class->lookup_certificate_issuer = g_tls_file_database_openssl_lookup_certificate_issuer;
- database_class->lookup_certificates_issued_by = g_tls_file_database_openssl_lookup_certificates_issued_by;
- database_class->verify_chain = g_tls_file_database_openssl_verify_chain;
-
- g_object_class_override_property (gobject_class, PROP_ANCHORS, "anchors");
-}
-
-static void
-g_tls_file_database_openssl_file_database_interface_init (GTlsFileDatabaseInterface *iface)
-{
-}
-
static gboolean
-g_tls_file_database_openssl_initable_init (GInitable *initable,
- GCancellable *cancellable,
- GError **error)
+g_tls_file_database_openssl_populate_trust_list (GTlsDatabaseOpenssl *self,
+ X509_STORE *store,
+ GError **error)
{
- GTlsFileDatabaseOpenssl *file_database = G_TLS_FILE_DATABASE_OPENSSL (initable);
+ GTlsFileDatabaseOpenssl *file_database = G_TLS_FILE_DATABASE_OPENSSL (self);
GTlsFileDatabaseOpensslPrivate *priv;
GHashTable *subjects, *issuers, *complete, *certs_by_handle;
gboolean result;
priv = g_tls_file_database_openssl_get_instance_private (file_database);
- if (g_cancellable_set_error_if_cancelled (cancellable, error))
- return FALSE;
+ if (!X509_STORE_load_locations (store, priv->anchor_filename, NULL))
+ {
+ g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ _("Failed to load file path: %s"),
+ ERR_error_string (ERR_get_error (), NULL));
+ return FALSE;
+ }
subjects = bytes_multi_table_new ();
issuers = bytes_multi_table_new ();
@@ -697,9 +505,6 @@ g_tls_file_database_openssl_initable_init (GInitable *initable,
else
result = TRUE;
- if (g_cancellable_set_error_if_cancelled (cancellable, error))
- result = FALSE;
-
if (result)
{
g_mutex_lock (&priv->mutex);
@@ -738,115 +543,27 @@ g_tls_file_database_openssl_initable_init (GInitable *initable,
}
static void
-g_tls_file_database_openssl_initable_interface_init (GInitableIface *iface)
-{
- iface->init = g_tls_file_database_openssl_initable_init;
-}
-
-GTlsCertificateFlags
-g_tls_file_database_openssl_verify_ocsp_response (GTlsDatabase *database,
- GTlsCertificate *chain,
- OCSP_RESPONSE *resp)
+g_tls_file_database_openssl_class_init (GTlsFileDatabaseOpensslClass *klass)
{
- GTlsCertificateFlags errors = 0;
-#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
- !defined(OPENSSL_NO_OCSP)
- GTlsFileDatabaseOpenssl *file_database;
- GTlsFileDatabaseOpensslPrivate *priv;
- STACK_OF(X509) *chain_openssl = NULL;
- X509_STORE *store = NULL;
- OCSP_BASICRESP *basic_resp = NULL;
- int ocsp_status = 0;
- int i;
-
- ocsp_status = OCSP_response_status (resp);
- if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL)
- {
- errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
- goto end;
- }
-
- basic_resp = OCSP_response_get1_basic (resp);
- if (basic_resp == NULL)
- {
- errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
- goto end;
- }
-
- chain_openssl = convert_certificate_chain_to_openssl (G_TLS_CERTIFICATE_OPENSSL (chain));
- file_database = G_TLS_FILE_DATABASE_OPENSSL (database);
- priv = g_tls_file_database_openssl_get_instance_private (file_database);
- store = X509_STORE_new ();
- if ((chain_openssl == NULL) ||
- (file_database == NULL) ||
- (priv == NULL) ||
- (priv->trusted == NULL) ||
- (store == NULL))
- {
- errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
- goto end;
- }
-
- for (i = 0; i < sk_X509_num (priv->trusted); i++)
- {
- X509_STORE_add_cert (store, sk_X509_value (priv->trusted, i));
- }
-
- if (OCSP_basic_verify (basic_resp, chain_openssl, store, 0) <= 0)
- {
- errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
- goto end;
- }
-
- for (i = 0; i < OCSP_resp_count (basic_resp); i++)
- {
- OCSP_SINGLERESP *single_resp = OCSP_resp_get0 (basic_resp, i);
- ASN1_GENERALIZEDTIME *revocation_time = NULL;
- ASN1_GENERALIZEDTIME *this_update_time = NULL;
- ASN1_GENERALIZEDTIME *next_update_time = NULL;
- int crl_reason = 0;
- int cert_status = 0;
-
- if (single_resp == NULL)
- continue;
-
- cert_status = OCSP_single_get0_status (single_resp,
- &crl_reason,
- &revocation_time,
- &this_update_time,
- &next_update_time);
- if (!OCSP_check_validity (this_update_time,
- next_update_time,
- 300L,
- -1L))
- {
- errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
- goto end;
- }
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GTlsDatabaseClass *database_class = G_TLS_DATABASE_CLASS (klass);
+ GTlsDatabaseOpensslClass *openssl_database_class = G_TLS_DATABASE_OPENSSL_CLASS (klass);
- switch (cert_status)
- {
- case V_OCSP_CERTSTATUS_GOOD:
- break;
- case V_OCSP_CERTSTATUS_REVOKED:
- errors = G_TLS_CERTIFICATE_REVOKED;
- goto end;
- case V_OCSP_CERTSTATUS_UNKNOWN:
- errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
- goto end;
- }
- }
+ gobject_class->get_property = g_tls_file_database_openssl_get_property;
+ gobject_class->set_property = g_tls_file_database_openssl_set_property;
+ gobject_class->finalize = g_tls_file_database_openssl_finalize;
-end:
- if (store != NULL)
- X509_STORE_free (store);
+ database_class->create_certificate_handle = g_tls_file_database_openssl_create_certificate_handle;
+ database_class->lookup_certificate_for_handle = g_tls_file_database_openssl_lookup_certificate_for_handle;
+ database_class->lookup_certificate_issuer = g_tls_file_database_openssl_lookup_certificate_issuer;
+ database_class->lookup_certificates_issued_by = g_tls_file_database_openssl_lookup_certificates_issued_by;
- if (basic_resp != NULL)
- OCSP_BASICRESP_free (basic_resp);
+ openssl_database_class->populate_trust_list = g_tls_file_database_openssl_populate_trust_list;
- if (resp != NULL)
- OCSP_RESPONSE_free (resp);
+ g_object_class_override_property (gobject_class, PROP_ANCHORS, "anchors");
+}
-#endif
- return errors;
+static void
+g_tls_file_database_openssl_file_database_interface_init (GTlsFileDatabaseInterface *iface)
+{
}
diff --git a/tls/openssl/gtlsfiledatabase-openssl.h b/tls/openssl/gtlsfiledatabase-openssl.h
index 67086db..66c2a22 100644
--- a/tls/openssl/gtlsfiledatabase-openssl.h
+++ b/tls/openssl/gtlsfiledatabase-openssl.h
@@ -53,10 +53,6 @@ struct _GTlsFileDatabaseOpenssl
GType g_tls_file_database_openssl_get_type (void) G_GNUC_CONST;
-GTlsCertificateFlags g_tls_file_database_openssl_verify_ocsp_response (GTlsDatabase *database,
- GTlsCertificate *chain,
- OCSP_RESPONSE *resp);
-
G_END_DECLS
#endif /* __G_TLS_FILE_DATABASE_OPENSSL_H___ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]