[glib-networking/mcatanzaro/tls-thread] progress?
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/mcatanzaro/tls-thread] progress?
- Date: Wed, 1 Jan 2020 16:03:18 +0000 (UTC)
commit 6f11c0aa76a1c4ac7b6a6c2901e2771c211f0cf8
Author: Michael Catanzaro <mcatanzaro gnome org>
Date: Wed Jan 1 08:42:39 2020 -0600
progress?
tls/base/gtlsoperationsthread-base.h | 1 -
tls/openssl/gtlsbio.c | 10 +-
tls/openssl/gtlsclientconnection-openssl.c | 298 ++---------------------
tls/openssl/gtlsconnection-openssl.c | 23 +-
tls/openssl/gtlsoperationsthread-openssl.c | 372 ++++++++++++++++++++++++++++-
tls/openssl/gtlsoperationsthread-openssl.h | 4 +-
tls/openssl/gtlsserverconnection-openssl.c | 171 +------------
7 files changed, 418 insertions(+), 461 deletions(-)
---
diff --git a/tls/base/gtlsoperationsthread-base.h b/tls/base/gtlsoperationsthread-base.h
index b167759..71f9662 100644
--- a/tls/base/gtlsoperationsthread-base.h
+++ b/tls/base/gtlsoperationsthread-base.h
@@ -213,5 +213,4 @@ GDatagramBased *g_tls_operations_thread_base_get_base_socket (GTl
gboolean g_tls_operations_thread_base_check (GTlsOperationsThreadBase
*self,
GIOCondition
condition);
-
G_END_DECLS
diff --git a/tls/openssl/gtlsbio.c b/tls/openssl/gtlsbio.c
index e19edd2..710cb57 100644
--- a/tls/openssl/gtlsbio.c
+++ b/tls/openssl/gtlsbio.c
@@ -221,16 +221,16 @@ gtls_bio_read (BIO *bio,
}
static int
-gtls_bio_puts(BIO *bio,
- const char *str)
+gtls_bio_puts (BIO *bio,
+ const char *str)
{
return gtls_bio_write (bio, str, (int)strlen (str));
}
static int
-gtls_bio_gets(BIO *bio,
- char *buf,
- int len)
+gtls_bio_gets (BIO *bio,
+ char *buf,
+ int len)
{
return -1;
}
diff --git a/tls/openssl/gtlsclientconnection-openssl.c b/tls/openssl/gtlsclientconnection-openssl.c
index 420f70c..5b31590 100644
--- a/tls/openssl/gtlsclientconnection-openssl.c
+++ b/tls/openssl/gtlsclientconnection-openssl.c
@@ -26,20 +26,19 @@
*/
#include "config.h"
-#include "glib.h"
-
-#include <errno.h>
-#include <string.h>
+#include "gtlsclientconnection-openssl.h"
#include "openssl-include.h"
#include "gtlsconnection-base.h"
-#include "gtlsclientconnection-openssl.h"
#include "gtlsbackend-openssl.h"
#include "gtlscertificate-openssl.h"
#include "gtlsdatabase-openssl.h"
-#include <glib/gi18n-lib.h>
+#include "gtlsoperationsthread-base.h"
-#define DEFAULT_CIPHER_LIST "HIGH:!DSS:!aNULL@STRENGTH"
+#include <errno.h>
+#include <glib.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
struct _GTlsClientConnectionOpenssl
{
@@ -55,10 +54,6 @@ struct _GTlsClientConnectionOpenssl
STACK_OF (X509_NAME) *ca_list;
gboolean ca_list_changed;
-
- SSL_SESSION *session;
- SSL *ssl;
- SSL_CTX *ssl_ctx;
};
enum
@@ -91,10 +86,6 @@ g_tls_client_connection_openssl_finalize (GObject *object)
g_clear_pointer (&openssl->session_id, g_bytes_unref);
g_clear_pointer (&openssl->session_data, g_bytes_unref);
- SSL_free (openssl->ssl);
- SSL_CTX_free (openssl->ssl_ctx);
- SSL_SESSION_free (openssl->session);
-
G_OBJECT_CLASS (g_tls_client_connection_openssl_parent_class)->finalize (object);
}
@@ -172,6 +163,7 @@ g_tls_client_connection_openssl_set_property (GObject *object,
GParamSpec *pspec)
{
GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
+ const gchar *hostname;
switch (prop_id)
{
@@ -183,6 +175,17 @@ g_tls_client_connection_openssl_set_property (GObject *object,
if (openssl->server_identity)
g_object_unref (openssl->server_identity);
openssl->server_identity = g_value_dup_object (value);
+
+ // FIXME: should allow unsetting server identity on op thread, and for GnuTLS too
+ hostname = get_server_identity (openssl);
+ if (hostname)
+ {
+ GTlsOperationsThreadBase *thread;
+
+ thread = g_tls_connection_base_get_op_thread (G_TLS_CONNECTION_BASE (openssl));
+ if (thread)
+ g_tls_operations_thread_base_set_server_identity (thread, hostname);
+ }
break;
case PROP_USE_SSL3:
@@ -194,54 +197,6 @@ g_tls_client_connection_openssl_set_property (GObject *object,
}
}
-static void
-g_tls_client_connection_openssl_constructed (GObject *object)
-{
- GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
- GSocketConnection *base_conn;
- GSocketAddress *remote_addr;
- GInetAddress *iaddr;
- guint port;
-
- /* Create a TLS session ID. We base it on the IP address since
- * different hosts serving the same hostname/service will probably
- * not share the same session cache. We base it on the
- * server-identity because at least some servers will fail (rather
- * than just failing to resume the session) if we don't.
- * (https://bugs.launchpad.net/bugs/823325)
- *
- * FIXME: this logic is broken because it doesn't consider the client
- * certificate when computing the session ID. The GnuTLS version of this
- * code has this problem fixed. Eliminate this code duplication.
- */
- g_object_get (G_OBJECT (openssl), "base-io-stream", &base_conn, NULL);
- if (G_IS_SOCKET_CONNECTION (base_conn))
- {
- remote_addr = g_socket_connection_get_remote_address (base_conn, NULL);
- if (G_IS_INET_SOCKET_ADDRESS (remote_addr))
- {
- GInetSocketAddress *isaddr = G_INET_SOCKET_ADDRESS (remote_addr);
- const gchar *server_hostname;
- gchar *addrstr, *session_id;
-
- iaddr = g_inet_socket_address_get_address (isaddr);
- port = g_inet_socket_address_get_port (isaddr);
-
- addrstr = g_inet_address_to_string (iaddr);
- server_hostname = get_server_identity (openssl);
- session_id = g_strdup_printf ("%s/%s/%d", addrstr,
- server_hostname ? server_hostname : "",
- port);
- openssl->session_id = g_bytes_new_take (session_id, strlen (session_id));
- g_free (addrstr);
- }
- g_object_unref (remote_addr);
- }
- g_object_unref (base_conn);
-
- G_OBJECT_CLASS (g_tls_client_connection_openssl_parent_class)->constructed (object);
-}
-
static GTlsCertificateFlags
verify_ocsp_response (GTlsClientConnectionOpenssl *openssl,
GTlsCertificate *peer_certificate)
@@ -279,6 +234,7 @@ verify_ocsp_response (GTlsClientConnectionOpenssl *openssl,
#endif
}
+// FIXME FIXME: looks important
static GTlsCertificateFlags
g_tls_client_connection_openssl_verify_peer_certificate (GTlsConnectionBase *tls,
GTlsCertificate *certificate,
@@ -292,12 +248,6 @@ g_tls_client_connection_openssl_verify_peer_certificate (GTlsConnectionBase *t
return flags;
}
-static SSL *
-g_tls_client_connection_openssl_get_ssl (GTlsConnectionOpenssl *connection)
-{
- return G_TLS_CLIENT_CONNECTION_OPENSSL (connection)->ssl;
-}
-
static void
g_tls_client_connection_openssl_class_init (GTlsClientConnectionOpensslClass *klass)
{
@@ -308,12 +258,9 @@ g_tls_client_connection_openssl_class_init (GTlsClientConnectionOpensslClass *kl
gobject_class->finalize = g_tls_client_connection_openssl_finalize;
gobject_class->get_property = g_tls_client_connection_openssl_get_property;
gobject_class->set_property = g_tls_client_connection_openssl_set_property;
- gobject_class->constructed = g_tls_client_connection_openssl_constructed;
base_class->verify_peer_certificate = g_tls_client_connection_openssl_verify_peer_certificate;
- openssl_class->get_ssl = g_tls_client_connection_openssl_get_ssl;
-
g_object_class_override_property (gobject_class, PROP_VALIDATION_FLAGS, "validation-flags");
g_object_class_override_property (gobject_class, PROP_SERVER_IDENTITY, "server-identity");
g_object_class_override_property (gobject_class, PROP_USE_SSL3, "use-ssl3");
@@ -338,219 +285,24 @@ g_tls_client_connection_openssl_client_connection_interface_init (GTlsClientConn
iface->copy_session_state = g_tls_client_connection_openssl_copy_session_state;
}
-static int data_index = -1;
-
-static int
-handshake_thread_retrieve_certificate (SSL *ssl,
- X509 **x509,
- EVP_PKEY **pkey)
-{
- GTlsClientConnectionOpenssl *client;
- GTlsConnectionBase *tls;
- GTlsCertificate *cert;
- gboolean had_ca_list;
-
- client = SSL_get_ex_data (ssl, data_index);
- tls = G_TLS_CONNECTION_BASE (client);
-
- had_ca_list = client->ca_list != NULL;
- client->ca_list = SSL_get_client_CA_list (client->ssl);
- client->ca_list_changed = client->ca_list || had_ca_list;
-
- cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
- if (!cert)
- {
- if (g_tls_connection_base_handshake_thread_request_certificate (tls))
- cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
- }
-
- if (cert)
- {
- EVP_PKEY *key;
-
- key = g_tls_certificate_openssl_get_key (G_TLS_CERTIFICATE_OPENSSL (cert));
- /* increase ref count */
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
- CRYPTO_add (&key->references, 1, CRYPTO_LOCK_EVP_PKEY);
-#else
- EVP_PKEY_up_ref (key);
-#endif
- *pkey = key;
-
- *x509 = X509_dup (g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (cert)));
-
- return 1;
- }
-
- g_tls_connection_base_handshake_thread_set_missing_requested_client_certificate (tls);
-
- return 0;
-}
-
-static int
-generate_session_id (SSL *ssl,
- unsigned char *id,
- unsigned int *id_len)
-{
- GTlsClientConnectionOpenssl *client;
- int len;
-
- client = SSL_get_ex_data (ssl, data_index);
-
- len = MIN (*id_len, g_bytes_get_size (client->session_id));
- memcpy (id, g_bytes_get_data (client->session_id, NULL), len);
-
- return 1;
-}
-
-static gboolean
-set_cipher_list (GTlsClientConnectionOpenssl *client,
- GError **error)
-{
- const gchar *cipher_list;
-
- cipher_list = g_getenv ("G_TLS_OPENSSL_CIPHER_LIST");
- if (!cipher_list)
- cipher_list = DEFAULT_CIPHER_LIST;
-
- if (!SSL_CTX_set_cipher_list (client->ssl_ctx, cipher_list))
- {
- g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
- _("Could not create TLS context: %s"),
- ERR_error_string (ERR_get_error (), NULL));
- return FALSE;
- }
-
- return TRUE;
-}
-
-#ifdef SSL_CTX_set1_sigalgs_list
-static void
-set_signature_algorithm_list (GTlsClientConnectionOpenssl *client)
-{
- const gchar *signature_algorithm_list;
-
- signature_algorithm_list = g_getenv ("G_TLS_OPENSSL_SIGNATURE_ALGORITHM_LIST");
- if (!signature_algorithm_list)
- return;
-
- SSL_CTX_set1_sigalgs_list (client->ssl_ctx, signature_algorithm_list);
-}
-#endif
-
-#ifdef SSL_CTX_set1_curves_list
-static void
-set_curve_list (GTlsClientConnectionOpenssl *client)
-{
- const gchar *curve_list;
-
- curve_list = g_getenv ("G_TLS_OPENSSL_CURVE_LIST");
- if (!curve_list)
- return;
-
- SSL_CTX_set1_curves_list (client->ssl_ctx, curve_list);
-}
-#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,
GError **error)
{
- GTlsClientConnectionOpenssl *client = G_TLS_CLIENT_CONNECTION_OPENSSL (initable);
- long options;
- const char *hostname;
-
- client->session = SSL_SESSION_new ();
-
- client->ssl_ctx = SSL_CTX_new (SSLv23_client_method ());
- if (!client->ssl_ctx)
- {
- g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
- _("Could not create TLS context: %s"),
- ERR_error_string (ERR_get_error (), NULL));
- return FALSE;
- }
+ GTlsClientConnectionOpenssl *client;
+ GTlsOperationsThreadBase *thread;
+ const gchar *hostname;
- if (!set_cipher_list (client, error))
+ if (!g_tls_client_connection_openssl_parent_initable_iface->init (initable, cancellable, error))
return FALSE;
- /* Only TLS 1.2 or higher */
- options = SSL_OP_NO_TICKET |
- SSL_OP_NO_COMPRESSION |
-#ifdef SSL_OP_NO_TLSv1_1
- SSL_OP_NO_TLSv1_1 |
-#endif
- SSL_OP_NO_SSLv2 |
- SSL_OP_NO_SSLv3 |
- SSL_OP_NO_TLSv1;
- SSL_CTX_set_options (client->ssl_ctx, options);
-
- SSL_CTX_clear_options (client->ssl_ctx, SSL_OP_LEGACY_SERVER_CONNECT);
-
hostname = get_server_identity (client);
-
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined (LIBRESSL_VERSION_NUMBER)
if (hostname)
{
- X509_VERIFY_PARAM *param;
-
- param = X509_VERIFY_PARAM_new ();
- X509_VERIFY_PARAM_set1_host (param, hostname, 0);
- SSL_CTX_set1_param (client->ssl_ctx, param);
- X509_VERIFY_PARAM_free (param);
+ thread = g_tls_connection_base_get_op_thread (G_TLS_CONNECTION_BASE (client));
+ g_tls_operations_thread_base_set_server_identity (thread, hostname);
}
-#endif
-
- SSL_CTX_set_generate_session_id (client->ssl_ctx, (GEN_SESSION_CB)generate_session_id);
-
- SSL_CTX_add_session (client->ssl_ctx, client->session);
-
- SSL_CTX_set_client_cert_cb (client->ssl_ctx, handshake_thread_retrieve_certificate);
-
-#ifdef SSL_CTX_set1_sigalgs_list
- set_signature_algorithm_list (client);
-#endif
-
-#ifdef SSL_CTX_set1_curves_list
- set_curve_list (client);
-#endif
-
- client->ssl = SSL_new (client->ssl_ctx);
- if (!client->ssl)
- {
- g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
- _("Could not create TLS connection: %s"),
- ERR_error_string (ERR_get_error (), NULL));
- return FALSE;
- }
-
- if (data_index == -1) {
- data_index = SSL_get_ex_new_index (0, (void *)"gtlsclientconnection", NULL, NULL, NULL);
- }
- SSL_set_ex_data (client->ssl, data_index, client);
-
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- if (hostname)
- SSL_set_tlsext_host_name (client->ssl, hostname);
-#endif
-
- 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;
return TRUE;
}
diff --git a/tls/openssl/gtlsconnection-openssl.c b/tls/openssl/gtlsconnection-openssl.c
index 9833612..8260232 100644
--- a/tls/openssl/gtlsconnection-openssl.c
+++ b/tls/openssl/gtlsconnection-openssl.c
@@ -58,7 +58,24 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GTlsConnectionOpenssl, g_tls_connection_openss
static GTlsOperationsThreadBase *
g_tls_connection_openssl_create_op_thread (GTlsConnectionBase *tls)
{
- return g_tls_operations_thread_openssl_new (G_TLS_CONNECTION_OPENSSL (tls));
+ GTlsOperationsThreadBase *thread;
+ GTlsOperationsThreadType thread_type;
+ GIOStream *base_iostream = NULL;
+
+ g_object_get (tls,
+ "base-io-stream", &base_iostream,
+ NULL);
+
+ if (G_IS_TLS_CLIENT_CONNECTION (tls))
+ thread_type = G_TLS_OPERATIONS_THREAD_CLIENT;
+ else
+ thread_type = G_TLS_OPERATIONS_THREAD_SERVER;
+
+ thread = g_tls_operations_thread_openssl_new (base_iostream,
+ thread_type);
+ g_object_unref (base_iostream);
+
+ return thread;
}
static GTlsCertificate *
@@ -191,6 +208,8 @@ g_tls_connection_openssl_initable_init (GInitable *initable,
SSL_set_bio (ssl, priv->bio, priv->bio);
+ g_object_unref (base_io_stream);
+
return g_tls_connection_openssl_parent_initable_iface->init (initable, cancellable, error);
}
@@ -207,6 +226,7 @@ g_tls_connection_openssl_init (GTlsConnectionOpenssl *openssl)
{
}
+// FIXME: remove
SSL *
g_tls_connection_openssl_get_ssl (GTlsConnectionOpenssl *openssl)
{
@@ -215,6 +235,7 @@ g_tls_connection_openssl_get_ssl (GTlsConnectionOpenssl *openssl)
return G_TLS_CONNECTION_OPENSSL_GET_CLASS (openssl)->get_ssl (openssl);
}
+// FIXME: remove
GTlsConnectionOpenssl *
g_tls_connection_openssl_get_connection_from_ssl (SSL *ssl)
{
diff --git a/tls/openssl/gtlsoperationsthread-openssl.c b/tls/openssl/gtlsoperationsthread-openssl.c
index e67bbee..41414bb 100644
--- a/tls/openssl/gtlsoperationsthread-openssl.c
+++ b/tls/openssl/gtlsoperationsthread-openssl.c
@@ -31,10 +31,18 @@
#include <glib/gi18n-lib.h>
+#define DEFAULT_CIPHER_LIST "HIGH:!DSS:!aNULL@STRENGTH"
+
+static int data_index = -1;
+
struct _GTlsOperationsThreadOpenssl {
GTlsOperationsThreadBase parent_instance;
+ GTlsOperationsThreadType thread_type;
+
+ SSL_SESSION *session;
SSL *ssl;
+ SSL_CTX *ssl_ctx;
gboolean shutting_down;
};
@@ -48,6 +56,43 @@ G_DEFINE_TYPE_WITH_CODE (GTlsOperationsThreadOpenssl, g_tls_operations_thread_op
g_tls_operations_thread_openssl_initable_iface_init);
)
+static inline gboolean
+is_client (GTlsOperationsThreadOpenssl *self)
+{
+ return self->thread_type == G_TLS_OPERATIONS_THREAD_CLIENT;
+}
+
+static inline gboolean
+is_server (GTlsOperationsThreadOpenssl *self)
+{
+ return self->thread_type == G_TLS_OPERATIONS_THREAD_SERVER;
+}
+
+static void
+g_tls_operations_thread_openssl_set_server_identity (GTlsOperationsThreadBase *base,
+ const gchar *server_identity)
+{
+ GTlsOperationsThreadOpenssl *self = G_TLS_OPERATIONS_THREAD_OPENSSL (base);
+
+ g_assert (is_client (self));
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined (LIBRESSL_VERSION_NUMBER)
+ if (server_identity)
+ {
+ X509_VERIFY_PARAM *param;
+
+ param = X509_VERIFY_PARAM_new ();
+ X509_VERIFY_PARAM_set1_host (param, server_identity, 0);
+ SSL_CTX_set1_param (self->ssl_ctx, param);
+ X509_VERIFY_PARAM_free (param);
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ SSL_set_tlsext_host_name (self->ssl, server_identity);
+#endif
+ }
+#endif
+}
+
static GTlsOperationStatus
end_openssl_io (GTlsOperationsThreadOpenssl *self,
GIOCondition direction,
@@ -273,19 +318,322 @@ g_tls_operations_thread_openssl_close (GTlsOperationsThreadBase *base,
return status;
}
+static gboolean
+set_cipher_list (GTlsOperationsThreadOpenssl *self,
+ GError **error)
+{
+ const gchar *cipher_list;
+
+ cipher_list = g_getenv ("G_TLS_OPENSSL_CIPHER_LIST");
+ if (!cipher_list)
+ cipher_list = DEFAULT_CIPHER_LIST;
+
+ if (!SSL_CTX_set_cipher_list (self->ssl_ctx, cipher_list))
+ {
+ g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ _("Could not create TLS context: %s"),
+ ERR_error_string (ERR_get_error (), NULL));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#ifdef SSL_CTX_set1_sigalgs_list
+static void
+set_signature_algorithm_list (GTlsOperationsThreadOpenssl *self)
+{
+ const gchar *signature_algorithm_list;
+
+ signature_algorithm_list = g_getenv ("G_TLS_OPENSSL_SIGNATURE_ALGORITHM_LIST");
+ if (!signature_algorithm_list)
+ return;
+
+ SSL_CTX_set1_sigalgs_list (self->ssl_ctx, signature_algorithm_list);
+}
+#endif
+
+#ifdef SSL_CTX_set1_curves_list
+static void
+set_curve_list (GTlsOperationsThreadOpenssl *self)
+{
+ const gchar *curve_list;
+
+ curve_list = g_getenv ("G_TLS_OPENSSL_CURVE_LIST");
+ if (!curve_list)
+ return;
+
+ SSL_CTX_set1_curves_list (self->ssl_ctx, curve_list);
+}
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
+static void
+ssl_info_callback (const SSL *ssl,
+ int type,
+ int val)
+{
+ g_assert (is_server (self));
+
+ if ((type & SSL_CB_HANDSHAKE_DONE) != 0)
+ {
+ /* Disable renegotiation (CVE-2009-3555) */
+ ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
+ }
+}
+#endif
+
+static void
+compute_session_id (GTlsOperationsThreadOpenssl *self)
+{
+ GSocketConnection *base_conn;
+ GSocketAddress *remote_addr;
+ GInetAddress *iaddr;
+ guint port;
+
+ /* FIXME: this logic is broken because it doesn't consider the client
+ * certificate when computing the session ID. The GnuTLS version of this
+ * code has this problem fixed. Eliminate this code duplication.
+ */
+ g_object_get (G_OBJECT (openssl), "base-io-stream", &base_conn, NULL);
+ if (G_IS_SOCKET_CONNECTION (base_conn))
+ {
+ remote_addr = g_socket_connection_get_remote_address (base_conn, NULL);
+ if (G_IS_INET_SOCKET_ADDRESS (remote_addr))
+ {
+ GInetSocketAddress *isaddr = G_INET_SOCKET_ADDRESS (remote_addr);
+ const gchar *server_hostname;
+ gchar *addrstr, *session_id;
+
+ iaddr = g_inet_socket_address_get_address (isaddr);
+ port = g_inet_socket_address_get_port (isaddr);
+
+ addrstr = g_inet_address_to_string (iaddr);
+ server_hostname = get_server_identity (openssl); /* FIXME: server identity won't be available
until after init... */
+ session_id = g_strdup_printf ("%s/%s/%d", addrstr,
+ server_hostname ? server_hostname : "",
+ port);
+ self->session_id = g_bytes_new_take (session_id, strlen (session_id));
+ g_free (addrstr);
+ }
+ g_object_unref (remote_addr);
+ }
+ g_object_unref (base_conn);
+}
+
+static int
+generate_session_id_cb (SSL *ssl,
+ unsigned char *id,
+ unsigned int *id_len)
+{
+ GTlsOperationsThreadOpenssl *self;
+ int len;
+
+ self = SSL_get_ex_data (ssl, data_index);
+
+ len = MIN (*id_len, g_bytes_get_size (self->session_id));
+ memcpy (id, g_bytes_get_data (self->session_id, NULL), len);
+
+ return 1;
+}
+
+static int
+retrieve_certificate_cb (SSL *ssl,
+ X509 **x509,
+ EVP_PKEY **pkey)
+{
+ GTlsOperationsThreadOpenssl *self;
+ GTlsConnectionBase *tls;
+ GTlsCertificate *cert;
+ gboolean had_ca_list;
+
+ self = SSL_get_ex_data (ssl, data_index);
+ tls = G_TLS_CONNECTION_BASE (client);
+
+ had_ca_list = self->ca_list != NULL;
+ self->ca_list = SSL_get_client_CA_list (client->ssl);
+ self->ca_list_changed = self->ca_list || had_ca_list;
+
+ cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
+ if (!cert)
+ {
+ if (g_tls_connection_base_handshake_thread_request_certificate (tls))
+ cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
+ }
+
+ if (cert)
+ {
+ EVP_PKEY *key;
+
+ key = g_tls_certificate_openssl_get_key (G_TLS_CERTIFICATE_OPENSSL (cert));
+ /* increase ref count */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
+ CRYPTO_add (&key->references, 1, CRYPTO_LOCK_EVP_PKEY);
+#else
+ EVP_PKEY_up_ref (key);
+#endif
+ *pkey = key;
+
+ *x509 = X509_dup (g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (cert)));
+
+ return 1;
+ }
+
+ g_tls_connection_base_handshake_thread_set_missing_requested_client_certificate (tls);
+
+ return 0;
+}
+
+static gboolean
+use_ocsp (void)
+{
+ return g_getenv ("G_TLS_OPENSSL_OCSP_ENABLED") != NULL;
+}
+
+static void
+g_tls_operations_thread_openssl_finalize (GObject *object)
+{
+ GTlsOperationsThreadOpenssl *self = G_TLS_OPERATIONS_THREAD_OPENSSL (object);
+
+ SSL_free (self->ssl);
+ SSL_CTX_free (self->ssl_ctx);
+ SSL_SESSION_free (self->session);
+
+ G_OBJECT_CLASS (g_tls_operations_thread_openssl_parent_class)->finalize (object);
+}
+
static gboolean
g_tls_operations_thread_openssl_initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
GTlsOperationsThreadOpenssl *self = G_TLS_OPERATIONS_THREAD_OPENSSL (initable);
- GTlsConnectionBase *openssl;
+ long options;
+ const char *hostname;
+ GTlsCertificate *cert; /* FIXME: remove, become part of handshake op? */
if (!g_tls_operations_thread_openssl_parent_initable_iface->init (initable, cancellable, error))
return FALSE;
- openssl = g_tls_operations_thread_base_get_connection (G_TLS_OPERATIONS_THREAD_BASE (self));
- self->ssl = g_tls_connection_openssl_get_ssl (G_TLS_CONNECTION_OPENSSL (openssl));
+ g_object_get (self,
+ "thread-type", &self->thread_type,
+ NULL);
+
+ if (is_client (self)) /* FIXME: broken */
+ compute_session_id (self);
+
+ self->session = SSL_SESSION_new ();
+ self->ssl_ctx = SSL_CTX_new (is_client (self) ? SSLv23_client_method () : SSLv23_server_method ());
+ if (!self->ssl_ctx)
+ {
+ g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ _("Could not create TLS context: %s"),
+ ERR_error_string (ERR_get_error (), NULL));
+ return FALSE;
+ }
+
+ if (!set_cipher_list (self, error))
+ return FALSE;
+
+ /* Only TLS 1.2 or higher */
+ options = SSL_OP_NO_TICKET |
+ SSL_OP_NO_COMPRESSION |
+#ifdef SSL_OP_NO_TLSv1_1
+ SSL_OP_NO_TLSv1_1 |
+#endif
+ SSL_OP_NO_SSLv2 |
+ SSL_OP_NO_SSLv3 |
+ SSL_OP_NO_TLSv1;
+
+ if (is_server (self))
+ {
+ SSL_CTX_set_options (self->ssl_ctx, options);
+ }
+ else
+ {
+ options |= SSL_OP_CIPHER_SERVER_PREFERENCE |
+ SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
+ SSL_OP_SINGLE_ECDH_USE;
+#ifdef SSL_OP_NO_RENEGOTIATION
+ options |= SSL_OP_NO_RENEGOTIATION;
+#endif
+ SSL_CTX_set_options (self->ssl_ctx, options);
+ SSL_CTX_clear_options (self->ssl_ctx, SSL_OP_LEGACY_SERVER_CONNECT);
+
+ SSL_CTX_set_generate_session_id (self->ssl_ctx, (GEN_SESSION_CB)generate_session_id_cb);
+
+ SSL_CTX_set_client_cert_cb (self->ssl_ctx, retrieve_certificate_cb);
+ }
+
+ SSL_CTX_add_session (self->ssl_ctx, self->session);
+
+#ifdef SSL_CTX_set1_sigalgs_list
+ set_signature_algorithm_list (server);
+#endif
+
+#ifdef SSL_CTX_set1_curves_list
+ set_curve_list (server);
+#endif
+
+ if (is_server (self))
+ {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
+# ifdef SSL_CTX_set_ecdh_auto
+ SSL_CTX_set_ecdh_auto (self->ssl_ctx, 1);
+# else
+ {
+ EC_KEY *ecdh;
+
+ ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
+ if (ecdh)
+ {
+ SSL_CTX_set_tmp_ecdh (self->ssl_ctx, ecdh);
+ EC_KEY_free (ecdh);
+ }
+ }
+# endif
+
+ SSL_CTX_set_info_callback (self->ssl_ctx, ssl_info_callback);
+#endif
+
+ cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (initable));
+
+#if OPENSSL_VERSION_NUMBER < 0x10002000L
+ if (cert && !ssl_ctx_set_certificate (server->ssl_ctx, cert, error))
+ return FALSE;
+#endif
+ }
+
+ self->ssl = SSL_new (self->ssl_ctx);
+ if (!self->ssl)
+ {
+ g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ _("Could not create TLS connection: %s"),
+ ERR_error_string (ERR_get_error (), NULL));
+ return FALSE;
+ }
+
+ if (data_index == -1)
+ data_index = SSL_get_ex_new_index (0, (void *)"gtlsoperationsthread", NULL, NULL, NULL);
+ SSL_set_ex_data (self->ssl, data_index, self);
+
+ if (is_client (self))
+ {
+ 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
+ }
+ else
+ {
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L || defined (LIBRESSL_VERSION_NUMBER)
+ if (cert && !ssl_set_certificate (server->ssl, cert, error))
+ return FALSE;
+#endif
+ SSL_set_accept_state (server->ssl);
+ }
return TRUE;
}
@@ -301,10 +649,14 @@ g_tls_operations_thread_openssl_class_init (GTlsOperationsThreadOpensslClass *kl
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GTlsOperationsThreadBaseClass *base_class = G_TLS_OPERATIONS_THREAD_BASE_CLASS (klass);
- base_class->handshake_fn = g_tls_operations_thread_openssl_handshake;
- base_class->read_fn = g_tls_operations_thread_openssl_read;
- base_class->write_fn = g_tls_operations_thread_openssl_write;
- base_class->close_fn = g_tls_operations_thread_openssl_close;
+ gobject_class->finalize = g_tls_operations_thread_openssl_finalize;
+
+ base_class->copy_certificate = g_tls_operations_thread_openssl_copy_certificate;
+ base_class->set_server_identity = g_tls_operations_thread_openssl_set_server_identity;
+ base_class->handshake_fn = g_tls_operations_thread_openssl_handshake;
+ base_class->read_fn = g_tls_operations_thread_openssl_read;
+ base_class->write_fn = g_tls_operations_thread_openssl_write;
+ base_class->close_fn = g_tls_operations_thread_openssl_close;
}
static void
@@ -316,12 +668,12 @@ g_tls_operations_thread_openssl_initable_iface_init (GInitableIface *iface)
}
GTlsOperationsThreadBase *
-g_tls_operations_thread_openssl_new (GTlsConnectionOpenssl *tls,
- GIOStream *base_iostream)
+g_tls_operations_thread_openssl_new (GIOStream *base_iostream,
+ GTlsOperationsThreadType type)
{
return g_initable_new (G_TYPE_TLS_OPERATIONS_THREAD_OPENSSL,
NULL, NULL,
"base-iostream", base_iostream,
- "tls-connection", tls,
+ "thread-type", type,
NULL);
}
diff --git a/tls/openssl/gtlsoperationsthread-openssl.h b/tls/openssl/gtlsoperationsthread-openssl.h
index 7441f3c..9a3ecc0 100644
--- a/tls/openssl/gtlsoperationsthread-openssl.h
+++ b/tls/openssl/gtlsoperationsthread-openssl.h
@@ -36,7 +36,7 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (GTlsOperationsThreadOpenssl, g_tls_operations_thread_openssl, G,
TLS_OPERATIONS_THREAD_OPENSSL, GTlsOperationsThreadBase)
-GTlsOperationsThreadBase *g_tls_operations_thread_openssl_new (GTlsConnectionOpenssl *tls,
- GIOStream *base_iostream);
+GTlsOperationsThreadBase *g_tls_operations_thread_openssl_new (GIOStream *base_iostream,
+ GTlsOperationsThreadType type);
G_END_DECLS
diff --git a/tls/openssl/gtlsserverconnection-openssl.c b/tls/openssl/gtlsserverconnection-openssl.c
index 2165ccb..ead2b8a 100644
--- a/tls/openssl/gtlsserverconnection-openssl.c
+++ b/tls/openssl/gtlsserverconnection-openssl.c
@@ -33,16 +33,11 @@
#include "openssl-include.h"
#include <glib/gi18n-lib.h>
-#define DEFAULT_CIPHER_LIST "HIGH:!DSS:!aNULL@STRENGTH"
-
struct _GTlsServerConnectionOpenssl
{
GTlsConnectionOpenssl parent_instance;
GTlsAuthenticationMode authentication_mode;
- SSL_SESSION *session;
- SSL *ssl;
- SSL_CTX *ssl_ctx;
};
enum
@@ -63,17 +58,6 @@ G_DEFINE_TYPE_WITH_CODE (GTlsServerConnectionOpenssl, g_tls_server_connection_op
G_IMPLEMENT_INTERFACE (G_TYPE_TLS_SERVER_CONNECTION,
g_tls_server_connection_openssl_server_connection_interface_init))
-static void
-g_tls_server_connection_openssl_finalize (GObject *object)
-{
- GTlsServerConnectionOpenssl *openssl = G_TLS_SERVER_CONNECTION_OPENSSL (object);
-
- SSL_free (openssl->ssl);
- SSL_CTX_free (openssl->ssl_ctx);
- SSL_SESSION_free (openssl->session);
-
- G_OBJECT_CLASS (g_tls_server_connection_openssl_parent_class)->finalize (object);
-}
static void
g_tls_server_connection_openssl_get_property (GObject *object,
@@ -296,7 +280,6 @@ g_tls_server_connection_openssl_class_init (GTlsServerConnectionOpensslClass *kl
GTlsConnectionBaseClass *base_class = G_TLS_CONNECTION_BASE_CLASS (klass);
GTlsConnectionOpensslClass *connection_class = G_TLS_CONNECTION_OPENSSL_CLASS (klass);
- gobject_class->finalize = g_tls_server_connection_openssl_finalize;
gobject_class->get_property = g_tls_server_connection_openssl_get_property;
gobject_class->set_property = g_tls_server_connection_openssl_set_property;
@@ -317,167 +300,17 @@ g_tls_server_connection_openssl_server_connection_interface_init (GTlsServerConn
{
}
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
-static void
-ssl_info_callback (const SSL *ssl,
- int type,
- int val)
-{
- if ((type & SSL_CB_HANDSHAKE_DONE) != 0)
- {
- /* Disable renegotiation (CVE-2009-3555) */
- ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
- }
-}
-#endif
-
-static gboolean
-set_cipher_list (GTlsServerConnectionOpenssl *server,
- GError **error)
-{
- const gchar *cipher_list;
-
- cipher_list = g_getenv ("G_TLS_OPENSSL_CIPHER_LIST");
- if (!cipher_list)
- cipher_list = DEFAULT_CIPHER_LIST;
-
- if (!SSL_CTX_set_cipher_list (server->ssl_ctx, cipher_list))
- {
- g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
- _("Could not create TLS context: %s"),
- ERR_error_string (ERR_get_error (), NULL));
- return FALSE;
- }
-
- return TRUE;
-}
-
-#ifdef SSL_CTX_set1_sigalgs_list
-static void
-set_signature_algorithm_list (GTlsServerConnectionOpenssl *server)
-{
- const gchar *signature_algorithm_list;
-
- signature_algorithm_list = g_getenv ("G_TLS_OPENSSL_SIGNATURE_ALGORITHM_LIST");
- if (!signature_algorithm_list)
- return;
-
- SSL_CTX_set1_sigalgs_list (server->ssl_ctx, signature_algorithm_list);
-}
-#endif
-
-#ifdef SSL_CTX_set1_curves_list
-static void
-set_curve_list (GTlsServerConnectionOpenssl *server)
-{
- const gchar *curve_list;
-
- curve_list = g_getenv ("G_TLS_OPENSSL_CURVE_LIST");
- if (!curve_list)
- return;
-
- SSL_CTX_set1_curves_list (server->ssl_ctx, curve_list);
-}
-#endif
-
static gboolean
g_tls_server_connection_openssl_initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
GTlsServerConnectionOpenssl *server = G_TLS_SERVER_CONNECTION_OPENSSL (initable);
- GTlsCertificate *cert;
- long options;
-
- server->session = SSL_SESSION_new ();
-
- server->ssl_ctx = SSL_CTX_new (SSLv23_server_method ());
- if (!server->ssl_ctx)
- {
- g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
- _("Could not create TLS context: %s"),
- ERR_error_string (ERR_get_error (), NULL));
- return FALSE;
- }
-
- if (!set_cipher_list (server, error))
- return FALSE;
-
- /* Only TLS 1.2 or higher */
- options = SSL_OP_NO_TICKET |
- SSL_OP_NO_COMPRESSION |
- SSL_OP_CIPHER_SERVER_PREFERENCE |
- SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
- SSL_OP_SINGLE_ECDH_USE |
-#ifdef SSL_OP_NO_TLSv1_1
- SSL_OP_NO_TLSv1_1 |
-#endif
- SSL_OP_NO_SSLv2 |
- SSL_OP_NO_SSLv3 |
- SSL_OP_NO_TLSv1;
-
-#ifdef SSL_OP_NO_RENEGOTIATION
- options |= SSL_OP_NO_RENEGOTIATION;
-#endif
-
- SSL_CTX_set_options (server->ssl_ctx, options);
-
- SSL_CTX_add_session (server->ssl_ctx, server->session);
-
-#ifdef SSL_CTX_set1_sigalgs_list
- set_signature_algorithm_list (server);
-#endif
-
-#ifdef SSL_CTX_set1_curves_list
- set_curve_list (server);
-#endif
-
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
-# ifdef SSL_CTX_set_ecdh_auto
- SSL_CTX_set_ecdh_auto (server->ssl_ctx, 1);
-# else
- {
- EC_KEY *ecdh;
-
- ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
- if (ecdh)
- {
- SSL_CTX_set_tmp_ecdh (server->ssl_ctx, ecdh);
- EC_KEY_free (ecdh);
- }
- }
-# endif
-
- SSL_CTX_set_info_callback (server->ssl_ctx, ssl_info_callback);
-#endif
-
- cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (initable));
-
-#if OPENSSL_VERSION_NUMBER < 0x10002000L
- if (cert && !ssl_ctx_set_certificate (server->ssl_ctx, cert, error))
- return FALSE;
-#endif
-
- server->ssl = SSL_new (server->ssl_ctx);
- if (!server->ssl)
- {
- g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
- _("Could not create TLS connection: %s"),
- ERR_error_string (ERR_get_error (), NULL));
- return FALSE;
- }
-
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L || defined (LIBRESSL_VERSION_NUMBER)
- if (cert && !ssl_set_certificate (server->ssl, cert, error))
- return FALSE;
-#endif
-
- SSL_set_accept_state (server->ssl);
- if (!g_tls_server_connection_openssl_parent_initable_iface->
- init (initable, cancellable, error))
+ if (!g_tls_server_connection_openssl_parent_initable_iface->init (initable, cancellable, error))
return FALSE;
+// FIXME: remove this
#if OPENSSL_VERSION_NUMBER >= 0x10002000L || defined (LIBRESSL_VERSION_NUMBER)
g_signal_connect (server, "notify::certificate", G_CALLBACK (on_certificate_changed), NULL);
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]