nss: implement non-blocking SSL handshake
This commit is contained in:
parent
a43bba3a34
commit
8868a226cd
@ -16,6 +16,7 @@ This release includes the following changes:
|
|||||||
o sasl: Added DIGEST-MD5 qop-option validation in native challange handling
|
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: Expanded mailbox SEARCH support to use URL query strings [7]
|
||||||
o imap: Extended FETCH support to include PARTIAL URL specifier [7]
|
o imap: Extended FETCH support to include PARTIAL URL specifier [7]
|
||||||
|
o nss: implement non-blocking SSL handshake
|
||||||
o
|
o
|
||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
@ -318,6 +318,7 @@ struct ssl_connect_data {
|
|||||||
struct SessionHandle *data;
|
struct SessionHandle *data;
|
||||||
struct curl_llist *obj_list;
|
struct curl_llist *obj_list;
|
||||||
PK11GenericObject *obj_clicert;
|
PK11GenericObject *obj_clicert;
|
||||||
|
ssl_connect_state connecting_state;
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#ifdef USE_QSOSSL
|
#ifdef USE_QSOSSL
|
||||||
SSLHandle *handle;
|
SSLHandle *handle;
|
||||||
|
@ -1611,7 +1611,10 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
|
|||||||
/* Force the handshake now */
|
/* Force the handshake now */
|
||||||
timeout = PR_MillisecondsToInterval((PRUint32) time_left);
|
timeout = PR_MillisecondsToInterval((PRUint32) time_left);
|
||||||
if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
|
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;
|
curlerr = CURLE_PEER_FAILED_VERIFICATION;
|
||||||
else if(conn->data->set.ssl.certverifyresult!=0)
|
else if(conn->data->set.ssl.certverifyresult!=0)
|
||||||
curlerr = CURLE_SSL_CACERT;
|
curlerr = CURLE_SSL_CACERT;
|
||||||
@ -1649,32 +1652,68 @@ error:
|
|||||||
return nss_fail_connect(connssl, data, curlerr);
|
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 ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
|
const bool blocking = (done == NULL);
|
||||||
CURLcode rv;
|
CURLcode rv;
|
||||||
|
|
||||||
|
if(connssl->connecting_state == ssl_connect_1) {
|
||||||
rv = nss_setup_connect(conn, sockindex);
|
rv = nss_setup_connect(conn, sockindex);
|
||||||
if(rv)
|
if(rv)
|
||||||
|
/* we do not expect CURLE_AGAIN from nss_setup_connect() */
|
||||||
return rv;
|
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);
|
rv = nss_do_connect(conn, sockindex);
|
||||||
switch(rv) {
|
switch(rv) {
|
||||||
case CURLE_OK:
|
case CURLE_OK:
|
||||||
break;
|
break;
|
||||||
|
case CURLE_AGAIN:
|
||||||
|
if(!blocking)
|
||||||
|
/* CURLE_AGAIN in non-blocking mode is not an error */
|
||||||
|
return CURLE_OK;
|
||||||
|
/* fall through */
|
||||||
default:
|
default:
|
||||||
return rv;
|
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);
|
rv = nss_set_nonblock(connssl, data);
|
||||||
if(rv)
|
if(rv)
|
||||||
return rv;
|
return rv;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* signal completed SSL handshake */
|
||||||
|
*done = TRUE;
|
||||||
|
|
||||||
|
connssl->connecting_state = ssl_connect_done;
|
||||||
return CURLE_OK;
|
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 */
|
static ssize_t nss_send(struct connectdata *conn, /* connection data */
|
||||||
int sockindex, /* socketindex */
|
int sockindex, /* socketindex */
|
||||||
const void *mem, /* send this data */
|
const void *mem, /* send this data */
|
||||||
|
@ -68,6 +68,7 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
|
|||||||
#define curlssl_init Curl_nss_init
|
#define curlssl_init Curl_nss_init
|
||||||
#define curlssl_cleanup Curl_nss_cleanup
|
#define curlssl_cleanup Curl_nss_cleanup
|
||||||
#define curlssl_connect Curl_nss_connect
|
#define curlssl_connect Curl_nss_connect
|
||||||
|
#define curlssl_connect_nonblocking Curl_nss_connect_nonblocking
|
||||||
|
|
||||||
/* NSS has its own session ID cache */
|
/* NSS has its own session ID cache */
|
||||||
#define curlssl_session_free(x) Curl_nop_stmt
|
#define curlssl_session_free(x) Curl_nop_stmt
|
||||||
|
Loading…
x
Reference in New Issue
Block a user