Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: d4aec0d998
Fetching contributors…

Cannot retrieve contributors at this time

91 lines (84 sloc) 3.015 kb
--- a/lib/gtls.c 2010-01-24 01:08:28 +0000
+++ b/lib/gtls.c 2010-01-24 01:10:15 +0000
@@ -85,15 +85,52 @@
* We use custom functions rather than the GNU TLS defaults because it allows
* us to get specific about the fourth "flags" argument, and to use arbitrary
* private data with gnutls_transport_set_ptr if we wish.
+ *
+ * On Windows translate WSAGetLastError() to errno values as GNU TLS does it
+ * internally too. This is necessary because send() and recv() on Windows
+ * don't set errno when they fail but GNU TLS expects a proper errno value.
+ *
+ * Use gnutls_transport_set_global_errno as the GNU TLS documentation suggests
+ * to avoid problems with different errno variables when GNU TLS and curl are
+ * linked to different versions of msvcrt.dll.
*/
+#ifdef USE_WINSOCK
+static void translate_wsa_to_errno(void)
+{
+ switch(WSAGetLastError()) {
+ case WSAEWOULDBLOCK:
+ gnutls_transport_set_global_errno(EAGAIN);
+ break;
+ case WSAEINTR:
+ gnutls_transport_set_global_errno(EINTR);
+ break;
+ default:
+ gnutls_transport_set_global_errno(EIO);
+ break;
+ }
+}
+#endif
+
static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
{
- return swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+ ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+#ifdef USE_WINSOCK
+ if(ret < 0) {
+ translate_wsa_to_errno();
+ }
+#endif
+ return ret;
}
static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
{
- return sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+ ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+#ifdef USE_WINSOCK
+ if(ret < 0) {
+ translate_wsa_to_errno();
+ }
+#endif
+ return ret;
}
/* Curl_gtls_init()
@@ -361,22 +398,28 @@
/* Use default priorities */
rc = gnutls_set_default_priority(session);
- if(rc != GNUTLS_E_SUCCESS)
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_set_default_priority() failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
+ }
if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) {
static const int protocol_priority[] = { GNUTLS_SSL3, 0 };
- gnutls_protocol_set_priority(session, protocol_priority);
- if(rc != GNUTLS_E_SUCCESS)
+ rc = gnutls_protocol_set_priority(session, protocol_priority);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_protocol_set_priority() failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
+ }
}
/* Sets the priority on the certificate types supported by gnutls. Priority
is higher for types specified before others. After specifying the types
you want, you must append a 0. */
rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
- if(rc != GNUTLS_E_SUCCESS)
+ if(rc != GNUTLS_E_SUCCESS && rc != GNUTLS_E_UNIMPLEMENTED_FEATURE) {
+ failf(data, "gnutls_certificate_type_set_priority() failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
+ }
if(data->set.str[STRING_CERT]) {
if( gnutls_certificate_set_x509_key_file(
Jump to Line
Something went wrong with that request. Please try again.