Hello,

here is a proposed patch implementing the workaround for TLS intolerant 
servers (taken from Firefox/xulrunner). I've just tested it as following
and it looks like it solves the problem:

$ curl --silent --verbose -o/dev/null https://www.orange.sk
$ curl --silent --verbose -o/dev/null \
    https://tcs.mysap.com/invoke/tc/getCert?SAPServerCA.der 

Any feedback welcome!

Kamil
Index: lib/nss.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/nss.c,v
retrieving revision 1.60
diff -u -p -r1.60 nss.c
--- lib/nss.c	7 Oct 2009 20:34:08 -0000	1.60
+++ lib/nss.c	14 Oct 2009 17:37:44 -0000
@@ -1070,7 +1070,9 @@ CURLcode Curl_nss_connect(struct connect
   switch (data->set.ssl.version) {
   default:
   case CURL_SSLVERSION_DEFAULT:
-    ssl3 = tlsv1 = PR_TRUE;
+    ssl3 = PR_TRUE;
+    if (!data->state.ssl_connect_retry)
+        tlsv1 = PR_TRUE;
     break;
   case CURL_SSLVERSION_TLSv1:
     tlsv1 = PR_TRUE;
@@ -1090,9 +1092,13 @@ CURLcode Curl_nss_connect(struct connect
   if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess)
     goto error;
 
-  if(SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess)
+  if(!data->state.ssl_connect_retry
+      && SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess)
     goto error;
 
+  /* reset the flag to avoid an infinite loop */
+  data->state.ssl_connect_retry = FALSE;
+
   /* enable all ciphers from enable_ciphers_by_default */
   cipher_to_enable = enable_ciphers_by_default;
   while (SSL_NULL_WITH_NULL_NULL != *cipher_to_enable) {
@@ -1270,10 +1276,34 @@ CURLcode Curl_nss_connect(struct connect
   return CURLE_OK;
 
 error:
+  /* reset the flag to avoid an infinite loop */
+  data->state.ssl_connect_retry = FALSE;
+
   err = PR_GetError();
   infof(data, "NSS error %d\n", err);
   if(model)
     PR_Close(model);
+
+  switch (err) {
+  case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
+  case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
+    /* these SSL errors are known to be suppressed by disabling TLSv1 and/or
+     * enabling SSL_V2_COMPATIBLE_HELLO, let's try to reconnect */
+
+    if (!ssl3 || !tlsv1)
+      /* this is either the second attempt or the SSL version was selected
+       * by user, so we should respect the selection */
+      break;
+
+    /* schedule reconnect through Curl_retry_request() */
+    infof(data, "peer seems to be TLS intolerant, trying reconnect...\n");
+    data->state.ssl_connect_retry = TRUE;
+    return CURLE_OK;
+
+  default:
+    break;
+  }
+
   return curlerr;
 }
 
Index: lib/transfer.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/transfer.c,v
retrieving revision 1.440
diff -u -p -r1.440 transfer.c
--- lib/transfer.c	27 Sep 2009 21:37:24 -0000	1.440
+++ lib/transfer.c	14 Oct 2009 17:37:45 -0000
@@ -2572,10 +2572,11 @@ CURLcode Curl_retry_request(struct conne
   if(data->set.upload && !(conn->protocol&PROT_HTTP))
     return CURLE_OK;
 
-  if((data->req.bytecount +
+  if(data->state.ssl_connect_retry ||
+      ((data->req.bytecount +
       data->req.headerbytecount == 0) &&
      conn->bits.reuse &&
-     !data->set.opt_no_body) {
+     !data->set.opt_no_body)) {
     /* We got no data, we attempted to re-use a connection and yet we want a
        "body". This might happen if the connection was left alive when we were
        done using it before, but that was closed when we wanted to read from
Index: lib/urldata.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/urldata.h,v
retrieving revision 1.419
diff -u -p -r1.419 urldata.h
--- lib/urldata.h	26 Sep 2009 08:31:48 -0000	1.419
+++ lib/urldata.h	14 Oct 2009 17:37:45 -0000
@@ -1327,6 +1327,9 @@ struct UrlState {
   } proto;
   /* current user of this SessionHandle instance, or NULL */
   struct connectdata *current_conn;
+
+  /* if true, force SSL connection retry (workaround for certain servers) */
+  bool ssl_connect_retry;
 };
 
 
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to