mirror of
https://github.com/moparisthebest/curl
synced 2024-11-11 12:05:06 -05:00
- libcurl-NSS now tries to reconnect with TLS disabled in case it detects
a broken TLS server. However it does not happen if SSL version is selected manually. The approach was originally taken from PSM. Kaspar Brand helped me to complete the patch. Original bug reports: https://bugzilla.redhat.com/525496 https://bugzilla.redhat.com/527771
This commit is contained in:
parent
d547d00f2c
commit
571309dc3e
7
CHANGES
7
CHANGES
@ -12,6 +12,13 @@ Kamil Dudka (12 Nov 2009)
|
||||
before and always closed unresolved. More info at the RH bug:
|
||||
https://bugzilla.redhat.com/534176
|
||||
|
||||
- libcurl-NSS now tries to reconnect with TLS disabled in case it detects
|
||||
a broken TLS server. However it does not happen if SSL version is selected
|
||||
manually. The approach was originally taken from PSM. Kaspar Brand helped me
|
||||
to complete the patch. Original bug reports:
|
||||
https://bugzilla.redhat.com/525496
|
||||
https://bugzilla.redhat.com/527771
|
||||
|
||||
Yang Tse (11 Nov 2009)
|
||||
- Marco Maggi reported that compilation failed when configured --with-gssapi
|
||||
and GNU GSS installed due to a missing mutual exclusion of header files in
|
||||
|
50
lib/nss.c
50
lib/nss.c
@ -844,6 +844,36 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* This function is supposed to decide, which error codes should be used
|
||||
* to conclude server is TLS intolerant.
|
||||
*
|
||||
* taken from xulrunner - nsNSSIOLayer.cpp
|
||||
*/
|
||||
static PRBool
|
||||
isTLSIntoleranceError(PRInt32 err)
|
||||
{
|
||||
switch (err) {
|
||||
case SSL_ERROR_BAD_MAC_ALERT:
|
||||
case SSL_ERROR_BAD_MAC_READ:
|
||||
case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
|
||||
case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
|
||||
case SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE:
|
||||
case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
|
||||
case SSL_ERROR_NO_CYPHER_OVERLAP:
|
||||
case SSL_ERROR_BAD_SERVER:
|
||||
case SSL_ERROR_BAD_BLOCK_PADDING:
|
||||
case SSL_ERROR_UNSUPPORTED_VERSION:
|
||||
case SSL_ERROR_PROTOCOL_VERSION_ALERT:
|
||||
case SSL_ERROR_RX_MALFORMED_FINISHED:
|
||||
case SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE:
|
||||
case SSL_ERROR_DECODE_ERROR_ALERT:
|
||||
case SSL_ERROR_RX_UNKNOWN_ALERT:
|
||||
return PR_TRUE;
|
||||
default:
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global SSL init
|
||||
*
|
||||
@ -1081,7 +1111,11 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||||
switch (data->set.ssl.version) {
|
||||
default:
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
ssl3 = tlsv1 = PR_TRUE;
|
||||
ssl3 = PR_TRUE;
|
||||
if (data->state.ssl_connect_retry)
|
||||
infof(data, "TLS disabled due to previous handshake failure\n");
|
||||
else
|
||||
tlsv1 = PR_TRUE;
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
tlsv1 = PR_TRUE;
|
||||
@ -1104,6 +1138,9 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||||
if(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) {
|
||||
@ -1282,10 +1319,21 @@ 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;
|
||||
|
||||
err = PR_GetError();
|
||||
infof(data, "NSS error %d\n", err);
|
||||
if(model)
|
||||
PR_Close(model);
|
||||
|
||||
if (ssl3 && tlsv1 && 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;
|
||||
}
|
||||
|
||||
|
@ -2572,10 +2572,11 @@ CURLcode Curl_retry_request(struct connectdata *conn,
|
||||
if(data->set.upload && !(conn->protocol&PROT_HTTP))
|
||||
return CURLE_OK;
|
||||
|
||||
if((data->req.bytecount +
|
||||
if(/* workaround for broken TLS servers */ 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
|
||||
|
@ -1331,6 +1331,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;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user