Commit 8868a226 authored by Kamil Dudka's avatar Kamil Dudka
Browse files

nss: implement non-blocking SSL handshake

parent a43bba3a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ This release includes the following changes:
 o sasl: Added DIGEST-MD5 qop-option validation in native challange handling
 o imap: Expanded mailbox SEARCH support to use URL query strings [7]
 o imap: Extended FETCH support to include PARTIAL URL specifier [7]
 o nss: implement non-blocking SSL handshake
 o 

This release includes the following bugfixes:
+1 −0
Original line number Diff line number Diff line
@@ -318,6 +318,7 @@ struct ssl_connect_data {
  struct SessionHandle *data;
  struct curl_llist *obj_list;
  PK11GenericObject *obj_clicert;
  ssl_connect_state connecting_state;
#endif /* USE_NSS */
#ifdef USE_QSOSSL
  SSLHandle *handle;
+48 −9
Original line number Diff line number Diff line
@@ -1611,7 +1611,10 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
  /* 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)
    if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
      /* TODO: propagate the blocking direction from the NSPR layer */
      return CURLE_AGAIN;
    else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
      curlerr = CURLE_PEER_FAILED_VERIFICATION;
    else if(conn->data->set.ssl.certverifyresult!=0)
      curlerr = CURLE_SSL_CACERT;
@@ -1649,32 +1652,68 @@ error:
  return nss_fail_connect(connssl, data, curlerr);
}

CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
                                   bool *done)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct SessionHandle *data = conn->data;
  const bool blocking = (done == NULL);
  CURLcode rv;

  if(connssl->connecting_state == ssl_connect_1) {
    rv = nss_setup_connect(conn, sockindex);
    if(rv)
      /* we do not expect CURLE_AGAIN from nss_setup_connect() */
      return rv;

    if(!blocking) {
      /* in non-blocking mode, set NSS non-blocking mode before handshake */
      rv = nss_set_nonblock(connssl, data);
      if(rv)
        return rv;
    }

    connssl->connecting_state = ssl_connect_2;
  }

  rv = nss_do_connect(conn, sockindex);
  switch(rv) {
  case CURLE_OK:
    break;
  case CURLE_AGAIN:
    if(!blocking)
      /* CURLE_AGAIN in non-blocking mode is not an error */
      return CURLE_OK;
    /* fall through */
  default:
    return rv;
  }

  /* switch the SSL socket into non-blocking mode */
  if(blocking) {
    /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
    rv = nss_set_nonblock(connssl, data);
    if(rv)
      return rv;
  }
  else
    /* signal completed SSL handshake */
    *done = TRUE;

  connssl->connecting_state = ssl_connect_done;
  return CURLE_OK;
}

CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
{
  return nss_connect_common(conn, sockindex, /* blocking */ NULL);
}

CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
                                      int sockindex, bool *done)
{
  return nss_connect_common(conn, sockindex, done);
}

static ssize_t nss_send(struct connectdata *conn,  /* connection data */
                        int sockindex,             /* socketindex */
                        const void *mem,           /* send this data */
+1 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
#define curlssl_init Curl_nss_init
#define curlssl_cleanup Curl_nss_cleanup
#define curlssl_connect Curl_nss_connect
#define curlssl_connect_nonblocking Curl_nss_connect_nonblocking

/* NSS has its own session ID cache */
#define curlssl_session_free(x) Curl_nop_stmt