Fixes for SSL/TLS support using GNUTLS under MinGW. Use send/recv

rather than read/write in TLS push/pull functions (works with winsock
and unix) and perform mappings between winsock error codes and
unix/gnutls error codes so that we correctly repeat operations whe they
fail in non-blockign mode.
This commit is contained in:
Richard Frith-Macdonald 2021-02-13 11:08:06 +00:00
parent 5c562c546f
commit b45feeb8d7
3 changed files with 70 additions and 11 deletions

View file

@ -1629,8 +1629,8 @@ debugWrite(GSHTTPURLHandle *handle, NSData *data)
if (sslClass == 0)
{
[self backgroundLoadDidFailWithReason:
@"https not supported ... needs SSL bundle"];
[self backgroundLoadDidFailWithReason: @"https not supported"
@" ... needs gnustep-base built with GNUTLS"];
return;
}
sock = [sslClass fileHandleAsClientInBackgroundAtAddress: host
@ -1675,8 +1675,8 @@ debugWrite(GSHTTPURLHandle *handle, NSData *data)
{
if (sslClass == 0)
{
[self backgroundLoadDidFailWithReason:
@"https not supported ... needs SSL bundle"];
[self backgroundLoadDidFailWithReason: @"https not supported"
@" ... needs gnustep-base built with GNUTLS"];
return;
}
host = [request objectForKey: GSHTTPPropertyProxyHostKey];

View file

@ -1936,6 +1936,7 @@ retrieve_callback(gnutls_session_t session,
{
int result = gnutls_record_recv(session, buf, len);
NSLog(@"TLS session read %d", result);
if (result < 0)
{
NSString *p;
@ -1975,6 +1976,17 @@ retrieve_callback(gnutls_session_t session,
errno = EAGAIN; // Need to retry.
}
result = -1;
#if defined(_WIN32)
/* Windows specific code expects to use winsock functions for error
* codes rather than looking at errno, so we must tyranslate a few.
*/
if (EAGAIN == errno)
WSASetLastError(WSAEWOULDBLOCK);
else if (EINTR == errno)
WSASetLastError(WSAEINTR);
else
WSASetLastError(errno);
#endif
}
return result;
}
@ -2013,6 +2025,17 @@ retrieve_callback(gnutls_session_t session,
errno = EAGAIN; // Need to retry.
}
result = -1;
#if defined(_WIN32)
/* Windows specific code expects to use winsock functions for error
* codes rather than looking at errno, so we must tyranslate a few.
*/
if (EAGAIN == errno)
WSASetLastError(WSAEWOULDBLOCK);
else if (EINTR == errno)
WSASetLastError(WSAEINTR);
else
WSASetLastError(errno);
#endif
}
return result;
}

View file

@ -943,15 +943,33 @@ GSTLSHandlePull(gnutls_transport_ptr_t handle, void *buffer, size_t len)
{
ssize_t result = 0;
GSTLSHandle *tls = (GSTLSHandle*)handle;
int descriptor = [tls fileDescriptor];
int descriptor = (int)(intptr_t)[tls nativeHandle];
result = read(descriptor, buffer, len);
result = recv(descriptor, buffer, len, 0);
if (result < 0)
{
#if HAVE_GNUTLS_TRANSPORT_SET_ERRNO
if (tls->session && tls->session->session)
{
gnutls_transport_set_errno (tls->session->session, errno);
int e;
#if defined(_WIN32)
/* For windows, we need to map winsock errors to unix ones that
* gnutls understands.
*/
e = WSAGetLastError();
if (WSAEWOULDBLOCK == e)
{
e = EAGAIN;
}
else if (WSAEINTR == e)
{
e = EINTR;
}
#else
e = errno;
#endif
gnutls_transport_set_errno (tls->session->session, e);
}
#endif
}
@ -966,15 +984,33 @@ GSTLSHandlePush(gnutls_transport_ptr_t handle, const void *buffer, size_t len)
{
ssize_t result = 0;
GSTLSHandle *tls = (GSTLSHandle*)handle;
int descriptor = [tls fileDescriptor];
int descriptor = (int)(intptr_t)[tls nativeHandle];
result = write(descriptor, buffer, len);
result = send(descriptor, buffer, len, 0);
if (result < 0)
{
#if HAVE_GNUTLS_TRANSPORT_SET_ERRNO
if (tls->session && tls->session->session)
{
gnutls_transport_set_errno (tls->session->session, errno);
int e;
#if defined(_WIN32)
/* For windows, we need to map winsock errors to unix ones that
* gnutls understands.
*/
e = WSAGetLastError();
if (WSAEWOULDBLOCK == e)
{
e = EAGAIN;
}
else if (WSAEINTR == e)
{
e = EINTR;
}
#else
e = errno;
#endif
gnutls_transport_set_errno(tls->session->session, e);
}
#endif
}
@ -1146,5 +1182,5 @@ GSTLSHandlePush(gnutls_transport_ptr_t handle, const void *buffer, size_t len)
@end
#endif /* defined(HAVE_GNUTLS) && !defined(_WIN32) */
#endif /* defined(HAVE_GNUTLS) */