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

Re: [libvirt] [PATCH] remote: Fix TLS transport on Windows



2010/11/22 Eric Blake <eblake redhat com>:
> On 11/22/2010 01:42 PM, Matthias Bolte wrote:
>>>> This doesn't entirely make any sense to me. GNUTLS also uses GNULIB,
>>>> including all its socket wrappers for send/recv. If the push/pull
>>>> function is NULL, gnulib does this
>>>>
>>>>      if (session->internals._gnutls_push_func == NULL)
>>>>        {
>>>>          i = send (GNUTLS_POINTER_TO_INT (fd), &ptr[n - left], left, 0);
>>>>
>>
>> Okay, yes GnuTLS uses gnulib, but they explicitly don't use gnulib's
>> replacements for send() and recv() on Windows. See
>> lib/gnutls_buffers.c:
>>
>> /* We need to disable gnulib's replacement wrappers to get native
>>    Windows interfaces. */
>> #undef recv
>> #undef send
>>
>> GnuTLS decided to use the native Windows versions of send() and
>> recv(). This cannot be changed, as that would break existing
>> applications using GnuTLS on Windows relying on GnuTLS using the
>> native Windows versions of send() and recv(). Therefore, I think my
>> patch is necessary, as libvirt requires GnuTLS to use gnulib's
>> replacement functions.
>
> Makes sense to me.  However, why the double cast?
>
> +#if HAVE_WINSOCK2_H
> +static ssize_t
> +custom_gnutls_push(void *s, const void *buf, size_t len)
> +{
> +    return send((int)(long)s, buf, len, 0);
> +}
> +
> +static ssize_t
> +custom_gnutls_pull(void *s, void *buf, size_t len)
> +{
> +    return recv((int)(long)s, buf, len, 0);
> +}
> +#endif
>
> Wouldn't send((size_t)s, ...) be better than send((int)(long)s,...)?
>

I just used what'a in curl, as directly casting from void* to int
would give this error on 64bit platform:

  error: cast from pointer to integer of different size [-Wpointer-to-int-cast]

(Yes, this is tested on Linux 64bit, as I didn't setup mingw-w64 yet)

Casting to size_t works too.

Here's a v2 that casts to size_t and has an improved commit message.

Matthias
From 4dd085a84d485599642fe4036ca68fd77aeb3419 Mon Sep 17 00:00:00 2001
From: Matthias Bolte <matthias bolte googlemail com>
Date: Sat, 20 Nov 2010 18:04:42 +0100
Subject: [PATCH] remote: Fix TLS transport on Windows

gnulib wraps Windows' SOCKET handle based send() and recv() functions
into file descriptor based ones that are used in libvirt.

Even though GnuTLS is using gnulib too, it explicitly doesn't use
gnulib's replacement functions on Windows. By default GnuTLS uses the
SOCKET handle based send() and recv(). This makes gnutls_handshake()
fail internally with a WSAENOTSOCK error because libvirt passes a
file descriptor; GnuTLS needs the SOCKET handle.

To avoid this mismatch make sure that GnuTLS uses gnulib's replacment
functions, by setting custom pull() and push() functions for GnuTLS.
---
 src/remote/remote_driver.c |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index f45476a..47a66dc 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1212,6 +1212,20 @@ initialize_gnutls(void)
 
 static int verify_certificate (virConnectPtr conn, struct private_data *priv, gnutls_session_t session);
 
+#if HAVE_WINSOCK2_H
+static ssize_t
+custom_gnutls_push(void *s, const void *buf, size_t len)
+{
+    return send((size_t)s, buf, len, 0);
+}
+
+static ssize_t
+custom_gnutls_pull(void *s, void *buf, size_t len)
+{
+    return recv((size_t)s, buf, len, 0);
+}
+#endif
+
 static gnutls_session_t
 negotiate_gnutls_on_connection (virConnectPtr conn,
                                 struct private_data *priv,
@@ -1266,6 +1280,13 @@ negotiate_gnutls_on_connection (virConnectPtr conn,
     gnutls_transport_set_ptr (session,
                               (gnutls_transport_ptr_t) (long) priv->sock);
 
+#if HAVE_WINSOCK2_H
+    /* Make sure GnuTLS uses gnulib's replacment functions for send() and
+     * recv() on Windows */
+    gnutls_transport_set_push_function(session, custom_gnutls_push);
+    gnutls_transport_set_pull_function(session, custom_gnutls_pull);
+#endif
+
     /* Perform the TLS handshake. */
  again:
     err = gnutls_handshake (session);
-- 
1.7.0.4


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