cURL / Mailing Lists / curl-library / Single Mail

curl-library

[PATCH 1/2] nss: split Curl_nss_connect() into 4 functions

From: Kamil Dudka <kdudka_at_redhat.com>
Date: Thu, 17 Apr 2014 15:13:25 +0200

---
 lib/vtls/nss.c |  134 +++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 94 insertions(+), 40 deletions(-)
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index 577716f..455648c 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -1296,9 +1296,62 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver,
   return CURLE_SSL_CONNECT_ERROR;
 }
 
-CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
+static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
+                                 struct SessionHandle *data,
+                                 CURLcode curlerr)
 {
+  SSLVersionRange sslver;
   PRErrorCode err = 0;
+
+  /* reset the flag to avoid an infinite loop */
+  data->state.ssl_connect_retry = FALSE;
+
+  if(is_nss_error(curlerr)) {
+    /* read NSPR error code */
+    err = PR_GetError();
+    if(is_cc_error(err))
+      curlerr = CURLE_SSL_CERTPROBLEM;
+
+    /* print the error number and error string */
+    infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err));
+
+    /* print a human-readable message describing the error if available */
+    nss_print_error_message(data, err);
+  }
+
+  /* cleanup on connection failure */
+  Curl_llist_destroy(connssl->obj_list, NULL);
+  connssl->obj_list = NULL;
+
+  if((SSL_VersionRangeGet(connssl->handle, &sslver) == SECSuccess)
+      && (sslver.min == SSL_LIBRARY_VERSION_3_0)
+      && (sslver.max == SSL_LIBRARY_VERSION_TLS_1_0)
+      && isTLSIntoleranceError(err)) {
+    /* schedule reconnect through Curl_retry_request() */
+    data->state.ssl_connect_retry = TRUE;
+    infof(data, "Error in TLS handshake, trying SSLv3...\n");
+    return CURLE_OK;
+  }
+
+  return curlerr;
+}
+
+/* Switch the SSL socket into non-blocking mode. */
+static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl,
+                                 struct SessionHandle *data)
+{
+  static PRSocketOptionData sock_opt;
+  sock_opt.option = PR_SockOpt_Nonblocking;
+  sock_opt.value.non_blocking = PR_TRUE;
+
+  if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
+    return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
+
+  return CURLE_OK;
+}
+
+static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
+{
   PRFileDesc *model = NULL;
   PRBool ssl_no_cache;
   PRBool ssl_cbc_random_iv;
@@ -1306,9 +1359,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
   curl_socket_t sockfd = conn->sock[sockindex];
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   CURLcode curlerr;
-  PRSocketOptionData sock_opt;
-  long time_left;
-  PRUint32 timeout;
 
   SSLVersionRange sslver = {
     SSL_LIBRARY_VERSION_3_0,      /* min */
@@ -1534,16 +1584,32 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
 
   SSL_SetURL(connssl->handle, conn->host.name);
 
+  return CURLE_OK;
+
+error:
+  if(model)
+    PR_Close(model);
+
+  return nss_fail_connect(connssl, data, curlerr);
+}
+
+static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
+{
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  struct SessionHandle *data = conn->data;
+  CURLcode curlerr = CURLE_SSL_CONNECT_ERROR;
+  PRUint32 timeout;
+
   /* check timeout situation */
-  time_left = Curl_timeleft(data, NULL, TRUE);
+  const long time_left = Curl_timeleft(data, NULL, TRUE);
   if(time_left < 0L) {
     failf(data, "timed out before SSL handshake");
     curlerr = CURLE_OPERATION_TIMEDOUT;
     goto error;
   }
-  timeout = PR_MillisecondsToInterval((PRUint32) time_left);
 
   /* Force the handshake now */
+  timeout = PR_MillisecondsToInterval((PRUint32) time_left);
   if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
     if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
       curlerr = CURLE_PEER_FAILED_VERIFICATION;
@@ -1552,12 +1618,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
     goto error;
   }
 
-  /* switch the SSL socket into non-blocking mode */
-  sock_opt.option = PR_SockOpt_Nonblocking;
-  sock_opt.value.non_blocking = PR_TRUE;
-  if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
-    goto error;
-
   connssl->state = ssl_connection_complete;
   conn->recv[sockindex] = nss_recv;
   conn->send[sockindex] = nss_send;
@@ -1585,40 +1645,34 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
 
   return CURLE_OK;
 
-  error:
-  /* reset the flag to avoid an infinite loop */
-  data->state.ssl_connect_retry = FALSE;
+error:
+  return nss_fail_connect(connssl, data, curlerr);
+}
 
-  if(is_nss_error(curlerr)) {
-    /* read NSPR error code */
-    err = PR_GetError();
-    if(is_cc_error(err))
-      curlerr = CURLE_SSL_CERTPROBLEM;
+CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
+{
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  struct SessionHandle *data = conn->data;
+  CURLcode rv;
 
-    /* print the error number and error string */
-    infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err));
+  rv = nss_setup_connect(conn, sockindex);
+  if(rv)
+    return rv;
 
-    /* print a human-readable message describing the error if available */
-    nss_print_error_message(data, err);
+  rv = nss_do_connect(conn, sockindex);
+  switch(rv) {
+  case CURLE_OK:
+    break;
+  default:
+    return rv;
   }
 
-  if(model)
-    PR_Close(model);
-
-  /* cleanup on connection failure */
-  Curl_llist_destroy(connssl->obj_list, NULL);
-  connssl->obj_list = NULL;
-
-  if((sslver.min == SSL_LIBRARY_VERSION_3_0)
-      && (sslver.max == SSL_LIBRARY_VERSION_TLS_1_0)
-      && isTLSIntoleranceError(err)) {
-    /* schedule reconnect through Curl_retry_request() */
-    data->state.ssl_connect_retry = TRUE;
-    infof(data, "Error in TLS handshake, trying SSLv3...\n");
-    return CURLE_OK;
-  }
+  /* switch the SSL socket into non-blocking mode */
+  rv = nss_set_nonblock(connssl, data);
+  if(rv)
+    return rv;
 
-  return curlerr;
+  return CURLE_OK;
 }
 
 static ssize_t nss_send(struct connectdata *conn,  /* connection data */
-- 
1.7.1
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html
Received on 2014-04-17