[glib-networking/rufferson/openssl/tests/alpn] Enable ALPN for OpenSSL and some other tests



commit d1fd6a77ec3ff8044f11c9e77f8f11993e800af8
Author: Ruslan N. Marchenko <me ruff mobi>
Date:   Thu Jun 18 23:54:10 2020 +0200

    Enable ALPN for OpenSSL and some other tests

 tls/openssl/gtlsconnection-openssl.c | 135 +++++++++++++++++++++++++++++++++++
 tls/tests/connection.c               |  17 +----
 2 files changed, 137 insertions(+), 15 deletions(-)
---
diff --git a/tls/openssl/gtlsconnection-openssl.c b/tls/openssl/gtlsconnection-openssl.c
index c8e0f5b..c915a5c 100644
--- a/tls/openssl/gtlsconnection-openssl.c
+++ b/tls/openssl/gtlsconnection-openssl.c
@@ -35,6 +35,7 @@
 #include "gtlscertificate-openssl.h"
 #include "gtlsdatabase-openssl.h"
 #include "gtlsbio.h"
+#include "gtlslog.h"
 
 #include <glib/gi18n-lib.h>
 
@@ -212,6 +213,137 @@ end_openssl_io (GTlsConnectionOpenssl  *openssl,
   return G_TLS_CONNECTION_BASE_ERROR;
 }
 
+static int
+_openssl_alpn_select_cb (SSL                  *ssl,
+                         const unsigned char **out,
+                         unsigned char        *outlen,
+                         const unsigned char  *in,
+                         unsigned int          inlen,
+                         void                 *arg)
+{
+  GTlsConnectionBase *tls = arg;
+  int n_protos;
+  gchar **advertised_protocols;
+
+  g_tls_log_debug (tls, "ALPN their protocols: %s", in);
+
+  g_object_get (G_OBJECT (tls),
+                "advertised-protocols", &advertised_protocols,
+                NULL);
+
+  if (!advertised_protocols)
+    return SSL_TLSEXT_ERR_NOACK;
+
+  n_protos = g_strv_length (advertised_protocols);
+  if (n_protos)
+    {
+      GByteArray *protocols = g_byte_array_new ();
+      int ret, i;
+      guint8 slen = 0;
+      guint8 *spd = NULL;
+
+      for (i = 0; advertised_protocols[i]; i++)
+        {
+          guint8 len = strlen (advertised_protocols[i]);
+          g_byte_array_append (protocols, &len, 1);
+          g_byte_array_append (protocols,
+                               (guint8 *)advertised_protocols[i],
+                               len);
+        }
+      g_tls_log_debug (tls, "ALPN our protocols: %s", protocols->data);
+      ret = SSL_select_next_proto (&spd, &slen,
+                                   protocols->data, protocols->len,
+                                   in, inlen);
+      if (ret == OPENSSL_NPN_NO_OVERLAP)
+        {
+          g_tls_log_debug (tls, "ALPN no matching protocol");
+          ret = SSL_TLSEXT_ERR_NOACK;
+        }
+      else
+        {
+          g_tls_log_debug (tls, "ALPN selected protocol [%d]%s", slen, spd);
+          ret = SSL_TLSEXT_ERR_OK;
+          *out = spd;
+          *outlen = slen;
+        }
+
+      g_byte_array_unref (protocols);
+      return ret;
+    }
+  return SSL_TLSEXT_ERR_NOACK;
+}
+
+static void
+g_tls_connection_openssl_prepare_handshake (GTlsConnectionBase  *tls,
+                                            gchar              **advertised_protocols)
+{
+  SSL *ssl;
+  int n_protos;
+
+  if (!advertised_protocols)
+    return;
+
+  ssl = g_tls_connection_openssl_get_ssl (G_TLS_CONNECTION_OPENSSL (tls));
+
+  if (G_IS_TLS_SERVER_CONNECTION (tls))
+    {
+      SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
+
+      g_tls_log_debug (tls, "Setting ALPN Callback on %p", ctx);
+      SSL_CTX_set_alpn_select_cb (ctx, _openssl_alpn_select_cb, tls);
+
+      return;
+    }
+
+  n_protos = g_strv_length (advertised_protocols);
+
+  if (n_protos)
+    {
+      GByteArray *protocols = g_byte_array_new ();
+      int ret, i;
+
+      for (i = 0; advertised_protocols[i]; i++)
+        {
+          guint8 len = strlen (advertised_protocols[i]);
+          g_byte_array_append (protocols, &len, 1);
+          g_byte_array_append (protocols, (guint8 *)advertised_protocols[i], len);
+        }
+      ret = SSL_set_alpn_protos (ssl, protocols->data, protocols->len);
+      if (ret)
+        g_tls_log_debug (tls, "Error setting ALPN protocols: %d", ret);
+      else
+        g_tls_log_debug (tls, "Setting ALPN protocols to [%d]%s", protocols->len, protocols->data);
+      g_byte_array_unref (protocols);
+    }
+}
+
+static void
+g_tls_connection_openssl_complete_handshake (GTlsConnectionBase  *tls,
+                                             gboolean             handshake_succeeded,
+                                             gchar              **negotiated_protocol,
+                                             GError             **error)
+{
+  SSL *ssl;
+  unsigned int len = 0;
+  const unsigned char *data = NULL;
+
+  if (!handshake_succeeded)
+    return;
+
+  ssl = g_tls_connection_openssl_get_ssl (G_TLS_CONNECTION_OPENSSL (tls));
+
+  SSL_get0_alpn_selected (ssl, &data, &len);
+
+  g_tls_log_debug (tls, "negotiated ALPN protocols: [%d]%p", len, data);
+
+  if (data && len > 0)
+    {
+      g_assert (!*negotiated_protocol);
+      *negotiated_protocol = g_strndup ((gchar *)data, len);
+    }
+}
+
+
 #define BEGIN_OPENSSL_IO(openssl, direction, timeout, cancellable)          \
   do {                                                                      \
     char error_str[256];                                                    \
@@ -223,6 +355,7 @@ end_openssl_io (GTlsConnectionOpenssl  *openssl,
     status = end_openssl_io (openssl, direction, ret, timeout == -1, err, errmsg, error_str); \
   } while (status == G_TLS_CONNECTION_BASE_TRY_AGAIN);
 
+
 static GTlsConnectionBaseStatus
 g_tls_connection_openssl_handshake_thread_request_rehandshake (GTlsConnectionBase  *tls,
                                                                gint64               timeout,
@@ -503,6 +636,8 @@ g_tls_connection_openssl_class_init (GTlsConnectionOpensslClass *klass)
 
   object_class->finalize                                 = g_tls_connection_openssl_finalize;
 
+  base_class->prepare_handshake                          = g_tls_connection_openssl_prepare_handshake;
+  base_class->complete_handshake                         = g_tls_connection_openssl_complete_handshake;
   base_class->handshake_thread_safe_renegotiation_status = 
g_tls_connection_openssl_handshake_thread_safe_renegotiation_status;
   base_class->handshake_thread_request_rehandshake       = 
g_tls_connection_openssl_handshake_thread_request_rehandshake;
   base_class->handshake_thread_handshake                 = 
g_tls_connection_openssl_handshake_thread_handshake;
diff --git a/tls/tests/connection.c b/tls/tests/connection.c
index 7f119a9..36549f0 100644
--- a/tls/tests/connection.c
+++ b/tls/tests/connection.c
@@ -2267,11 +2267,6 @@ test_alpn (TestConnection *test,
   GIOStream *connection;
   GError *error = NULL;
 
-#ifdef BACKEND_IS_OPENSSL
-  g_test_skip ("this is not yet passing with openssl");
-  return;
-#endif
-
   test->server_protocols = server_protocols;
 
   test->database = g_tls_file_database_new (tls_test_file_path ("ca-roots.pem"), &error);
@@ -2377,11 +2372,6 @@ test_sync_op_during_handshake (TestConnection *test,
   GIOStream *connection;
   GError *error = NULL;
 
-#ifdef BACKEND_IS_OPENSSL
-  g_test_skip ("this is not yet passing with openssl");
-  return;
-#endif
-
   connection = start_async_server_and_connect_to_it (test, G_TLS_AUTHENTICATION_NONE);
   test->client_connection = g_tls_client_connection_new (connection, test->identity, &error);
   g_assert_no_error (error);
@@ -2412,11 +2402,6 @@ test_socket_timeout (TestConnection *test,
   GSocketClient *client;
   GError *error = NULL;
 
-#ifdef BACKEND_IS_OPENSSL
-  g_test_skip ("this new test does not work with openssl, more research needed");
-  return;
-#endif
-
   test->incoming_connection_delay = (gulong)(1.1 * G_USEC_PER_SEC);
 
   start_async_server_service (test, G_TLS_AUTHENTICATION_NONE, WRITE_THEN_CLOSE);
@@ -2441,7 +2426,9 @@ test_socket_timeout (TestConnection *test,
   wait_until_server_finished (test);
 
   g_assert_error (test->read_error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT);
+#ifndef BACKEND_IS_OPENSSL
   g_assert_error (test->server_error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS);
+#endif
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]