[glib-networking/pgriffis/ocsp-openssl: 3/5] Revert "openssl: drop half-baked OCSP support"
- From: Patrick Griffis <pgriffis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/pgriffis/ocsp-openssl: 3/5] Revert "openssl: drop half-baked OCSP support"
- Date: Sat, 31 Jul 2021 23:42:58 +0000 (UTC)
commit 37f46818585a379c049af0128ec55e92c28cd744
Author: Patrick Griffis <pgriffis igalia com>
Date: Thu Jun 17 10:59:42 2021 -0500
Revert "openssl: drop half-baked OCSP support"
This reverts commit f21a57a04b55e2239a5df4b6aa47b3f7625c5c61.
tls/base/gtlsconnection-base.c | 4 ++
tls/base/gtlsconnection-base.h | 3 +
tls/openssl/gtlsclientconnection-openssl.c | 65 +++++++++++++++++++++
tls/openssl/gtlsdatabase-openssl.c | 93 ++++++++++++++++++++++++++++++
tls/openssl/gtlsdatabase-openssl.h | 4 ++
tls/openssl/openssl-include.h | 3 +
6 files changed, 172 insertions(+)
---
diff --git a/tls/base/gtlsconnection-base.c b/tls/base/gtlsconnection-base.c
index 6608b9b4..716f1631 100644
--- a/tls/base/gtlsconnection-base.c
+++ b/tls/base/gtlsconnection-base.c
@@ -1257,6 +1257,7 @@ static GTlsCertificateFlags
verify_peer_certificate (GTlsConnectionBase *tls,
GTlsCertificate *peer_certificate)
{
+ GTlsConnectionBaseClass *tls_class = G_TLS_CONNECTION_BASE_GET_CLASS (tls);
GSocketConnectable *peer_identity = NULL;
GTlsConnectionBaseClass *tls_class = G_TLS_CONNECTION_BASE_GET_CLASS (tls);
GTlsDatabase *database;
@@ -1303,6 +1304,9 @@ verify_peer_certificate (GTlsConnectionBase *tls,
}
}
+ if (tls_class->verify_peer_certificate)
+ errors |= tls_class->verify_peer_certificate (tls, peer_certificate, errors);
+
return errors;
}
diff --git a/tls/base/gtlsconnection-base.h b/tls/base/gtlsconnection-base.h
index a8c9b93f..06706607 100644
--- a/tls/base/gtlsconnection-base.h
+++ b/tls/base/gtlsconnection-base.h
@@ -80,6 +80,9 @@ struct _GTlsConnectionBaseClass
GTlsDatabaseVerifyFlags flags,
GCancellable *cancellable,
GError **error);
+ GTlsCertificateFlags (*verify_peer_certificate) (GTlsConnectionBase *tls,
+ GTlsCertificate *certificate,
+ GTlsCertificateFlags flags);
void (*complete_handshake) (GTlsConnectionBase *tls,
gboolean handshake_succeeded,
gchar **negotiated_protocol,
diff --git a/tls/openssl/gtlsclientconnection-openssl.c b/tls/openssl/gtlsclientconnection-openssl.c
index ff66e446..7573adb1 100644
--- a/tls/openssl/gtlsclientconnection-openssl.c
+++ b/tls/openssl/gtlsclientconnection-openssl.c
@@ -34,6 +34,7 @@
#include "gtlsclientconnection-openssl.h"
#include "gtlsbackend-openssl.h"
#include "gtlscertificate-openssl.h"
+#include "gtlsdatabase-openssl.h"
#include <glib/gi18n-lib.h>
struct _GTlsClientConnectionOpenssl
@@ -208,6 +209,56 @@ g_tls_client_connection_openssl_complete_handshake (GTlsConnectionBase *tls,
g_object_notify (G_OBJECT (client), "accepted-cas");
}
+static GTlsCertificateFlags
+verify_ocsp_response (GTlsClientConnectionOpenssl *openssl,
+ GTlsCertificate *peer_certificate)
+{
+#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_OCSP)
+ SSL *ssl = NULL;
+ OCSP_RESPONSE *resp = NULL;
+ GTlsDatabase *database;
+ long len = 0;
+ unsigned char *p = NULL;
+
+ ssl = g_tls_connection_openssl_get_ssl (G_TLS_CONNECTION_OPENSSL (openssl));
+ len = SSL_get_tlsext_status_ocsp_resp (ssl, &p);
+ /* Soft fail in case of no response is the best we can do
+ * FIXME: this makes it security theater, why bother with OCSP at all? */
+ if (!p)
+ return 0;
+
+ resp = d2i_OCSP_RESPONSE (NULL, (const unsigned char **)&p, len);
+ if (!resp)
+ return G_TLS_CERTIFICATE_GENERIC_ERROR;
+
+ database = g_tls_connection_get_database (G_TLS_CONNECTION (openssl));
+
+ /* If there's no database, then G_TLS_CERTIFICATE_UNKNOWN_CA must be flagged,
+ * and this function is only called if there are no flags.
+ */
+ g_assert (database);
+
+ return g_tls_database_openssl_verify_ocsp_response (G_TLS_DATABASE_OPENSSL (database),
+ peer_certificate,
+ resp);
+#else
+ return 0;
+#endif
+}
+
+static GTlsCertificateFlags
+g_tls_client_connection_openssl_verify_peer_certificate (GTlsConnectionBase *tls,
+ GTlsCertificate *certificate,
+ GTlsCertificateFlags flags)
+{
+ GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (tls);
+
+ if (flags == 0)
+ flags = verify_ocsp_response (openssl, certificate);
+
+ return flags;
+}
+
static SSL *
g_tls_client_connection_openssl_get_ssl (GTlsConnectionOpenssl *connection)
{
@@ -226,6 +277,7 @@ g_tls_client_connection_openssl_class_init (GTlsClientConnectionOpensslClass *kl
gobject_class->set_property = g_tls_client_connection_openssl_set_property;
base_class->complete_handshake = g_tls_client_connection_openssl_complete_handshake;
+ base_class->verify_peer_certificate = g_tls_client_connection_openssl_verify_peer_certificate;
openssl_class->get_ssl = g_tls_client_connection_openssl_get_ssl;
@@ -240,6 +292,7 @@ g_tls_client_connection_openssl_init (GTlsClientConnectionOpenssl *openssl)
{
}
+
static void
g_tls_client_connection_openssl_copy_session_state (GTlsClientConnection *conn,
GTlsClientConnection *source)
@@ -379,6 +432,12 @@ set_curve_list (GTlsClientConnectionOpenssl *client)
}
#endif
+static gboolean
+use_ocsp (void)
+{
+ return g_getenv ("G_TLS_OPENSSL_OCSP_ENABLED") != NULL;
+}
+
static gboolean
g_tls_client_connection_openssl_initable_init (GInitable *initable,
GCancellable *cancellable,
@@ -470,6 +529,12 @@ g_tls_client_connection_openssl_initable_init (GInitable *initable,
SSL_set_connect_state (client->ssl);
+#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
+ !defined(OPENSSL_NO_OCSP)
+ if (use_ocsp())
+ SSL_set_tlsext_status_type (client->ssl, TLSEXT_STATUSTYPE_ocsp);
+#endif
+
if (!g_tls_client_connection_openssl_parent_initable_iface->
init (initable, cancellable, error))
return FALSE;
diff --git a/tls/openssl/gtlsdatabase-openssl.c b/tls/openssl/gtlsdatabase-openssl.c
index 6cf2f492..65b5ff42 100644
--- a/tls/openssl/gtlsdatabase-openssl.c
+++ b/tls/openssl/gtlsdatabase-openssl.c
@@ -312,3 +312,96 @@ g_tls_database_openssl_new (GError **error)
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)
+ OCSP_BASICRESP_free (basic_resp);
+
+ if (resp)
+ OCSP_RESPONSE_free (resp);
+
+#endif
+ return errors;
+}
diff --git a/tls/openssl/gtlsdatabase-openssl.h b/tls/openssl/gtlsdatabase-openssl.h
index 092fdee8..f3203c0d 100644
--- a/tls/openssl/gtlsdatabase-openssl.h
+++ b/tls/openssl/gtlsdatabase-openssl.h
@@ -46,4 +46,8 @@ struct _GTlsDatabaseOpensslClass
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/openssl-include.h b/tls/openssl/openssl-include.h
index 7d394d5a..408d9ddd 100644
--- a/tls/openssl/openssl-include.h
+++ b/tls/openssl/openssl-include.h
@@ -51,3 +51,6 @@
#include <openssl/x509_vfy.h>
#include <openssl/x509v3.h>
#include <openssl/crypto.h>
+#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
+#include <openssl/ocsp.h>
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]