mirror of
https://github.com/moparisthebest/curl
synced 2024-08-13 17:03:50 -04:00
openssl: fix thread-safety bugs in error-handling
ERR_error_string with NULL parameter is not thread-safe. The library writes the string into some static buffer. Two threads doing this at once may clobber each other and run into problems. Switch to ERR_error_string_n which avoids this problem and is explicitly bounds-checked. Also clean up some remnants of OpenSSL 0.9.5 around here. A number of comments (fixed buffer size, explaining that ERR_error_string_n was added in a particular version) date to when ossl_strerror tried to support pre-ERR_error_string_n OpenSSLs. Closes #1424
This commit is contained in:
parent
47b2f89d7c
commit
1c92b5b609
@ -200,6 +200,14 @@ static const char *SSL_ERROR_to_str(int err)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return error string for last OpenSSL error
|
||||||
|
*/
|
||||||
|
static char *ossl_strerror(unsigned long error, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
ERR_error_string_n(error, buf, size);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
static int passwd_callback(char *buf, int num, int encrypting,
|
static int passwd_callback(char *buf, int num, int encrypting,
|
||||||
void *global_passwd)
|
void *global_passwd)
|
||||||
{
|
{
|
||||||
@ -375,6 +383,7 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
char *key_passwd)
|
char *key_passwd)
|
||||||
{
|
{
|
||||||
struct Curl_easy *data = conn->data;
|
struct Curl_easy *data = conn->data;
|
||||||
|
char error_buffer[256];
|
||||||
|
|
||||||
int file_type = do_file_type(cert_type);
|
int file_type = do_file_type(cert_type);
|
||||||
|
|
||||||
@ -400,7 +409,8 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
"could not load PEM client certificate, " OSSL_PACKAGE
|
"could not load PEM client certificate, " OSSL_PACKAGE
|
||||||
" error %s, "
|
" error %s, "
|
||||||
"(no key found, wrong pass phrase, or wrong file format?)",
|
"(no key found, wrong pass phrase, or wrong file format?)",
|
||||||
ERR_error_string(ERR_get_error(), NULL) );
|
ossl_strerror(ERR_get_error(), error_buffer,
|
||||||
|
sizeof(error_buffer)) );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -416,7 +426,8 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
"could not load ASN1 client certificate, " OSSL_PACKAGE
|
"could not load ASN1 client certificate, " OSSL_PACKAGE
|
||||||
" error %s, "
|
" error %s, "
|
||||||
"(no key found, wrong pass phrase, or wrong file format?)",
|
"(no key found, wrong pass phrase, or wrong file format?)",
|
||||||
ERR_error_string(ERR_get_error(), NULL) );
|
ossl_strerror(ERR_get_error(), error_buffer,
|
||||||
|
sizeof(error_buffer)) );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -445,7 +456,8 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
0, ¶ms, NULL, 1)) {
|
0, ¶ms, NULL, 1)) {
|
||||||
failf(data, "ssl engine cannot load client cert with id"
|
failf(data, "ssl engine cannot load client cert with id"
|
||||||
" '%s' [%s]", cert_file,
|
" '%s' [%s]", cert_file,
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ossl_strerror(ERR_get_error(), error_buffer,
|
||||||
|
sizeof(error_buffer)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,7 +513,8 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
failf(data,
|
failf(data,
|
||||||
"could not parse PKCS12 file, check password, " OSSL_PACKAGE
|
"could not parse PKCS12 file, check password, " OSSL_PACKAGE
|
||||||
" error %s",
|
" error %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL) );
|
ossl_strerror(ERR_get_error(), error_buffer,
|
||||||
|
sizeof(error_buffer)) );
|
||||||
PKCS12_free(p12);
|
PKCS12_free(p12);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -512,7 +525,8 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
failf(data,
|
failf(data,
|
||||||
"could not load PKCS12 client certificate, " OSSL_PACKAGE
|
"could not load PKCS12 client certificate, " OSSL_PACKAGE
|
||||||
" error %s",
|
" error %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL) );
|
ossl_strerror(ERR_get_error(), error_buffer,
|
||||||
|
sizeof(error_buffer)) );
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -703,17 +717,6 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return error string for last OpenSSL error
|
|
||||||
*/
|
|
||||||
static char *ossl_strerror(unsigned long error, char *buf, size_t size)
|
|
||||||
{
|
|
||||||
/* OpenSSL 0.9.6 and later has a function named
|
|
||||||
ERR_error_string_n() that takes the size of the buffer as a
|
|
||||||
third argument */
|
|
||||||
ERR_error_string_n(error, buf, size);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global SSL init
|
* Global SSL init
|
||||||
*
|
*
|
||||||
@ -1845,6 +1848,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
|
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
|
||||||
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
|
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
|
||||||
const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
|
const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
|
||||||
|
char error_buffer[256];
|
||||||
|
|
||||||
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
|
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
|
||||||
|
|
||||||
@ -1910,7 +1914,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
|
|
||||||
if(!connssl->ctx) {
|
if(!connssl->ctx) {
|
||||||
failf(data, "SSL: couldn't create a context: %s",
|
failf(data, "SSL: couldn't create a context: %s",
|
||||||
ERR_error_string(ERR_peek_error(), NULL));
|
ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer)));
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2240,7 +2244,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
|
if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
|
||||||
Curl_ssl_sessionid_unlock(conn);
|
Curl_ssl_sessionid_unlock(conn);
|
||||||
failf(data, "SSL: SSL_set_session failed: %s",
|
failf(data, "SSL: SSL_set_session failed: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ossl_strerror(ERR_get_error(), error_buffer,
|
||||||
|
sizeof(error_buffer)));
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
/* Informational message */
|
/* Informational message */
|
||||||
@ -2260,7 +2265,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
else if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
|
else if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
|
||||||
/* pass the raw socket into the SSL layers */
|
/* pass the raw socket into the SSL layers */
|
||||||
failf(data, "SSL: SSL_set_fd failed: %s",
|
failf(data, "SSL: SSL_set_fd failed: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2301,8 +2306,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
|
|||||||
else {
|
else {
|
||||||
/* untreated error */
|
/* untreated error */
|
||||||
unsigned long errdetail;
|
unsigned long errdetail;
|
||||||
char error_buffer[256]=""; /* OpenSSL documents that this must be at
|
char error_buffer[256]="";
|
||||||
least 256 bytes long. */
|
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
long lerr;
|
long lerr;
|
||||||
int lib;
|
int lib;
|
||||||
@ -3198,8 +3202,7 @@ static ssize_t ossl_send(struct connectdata *conn,
|
|||||||
/* SSL_write() is said to return 'int' while write() and send() returns
|
/* SSL_write() is said to return 'int' while write() and send() returns
|
||||||
'size_t' */
|
'size_t' */
|
||||||
int err;
|
int err;
|
||||||
char error_buffer[256]; /* OpenSSL documents that this must be at least 256
|
char error_buffer[256];
|
||||||
bytes long. */
|
|
||||||
unsigned long sslerror;
|
unsigned long sslerror;
|
||||||
int memlen;
|
int memlen;
|
||||||
int rc;
|
int rc;
|
||||||
@ -3260,8 +3263,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
|
|||||||
size_t buffersize, /* max amount to read */
|
size_t buffersize, /* max amount to read */
|
||||||
CURLcode *curlcode)
|
CURLcode *curlcode)
|
||||||
{
|
{
|
||||||
char error_buffer[256]; /* OpenSSL documents that this must be at
|
char error_buffer[256];
|
||||||
least 256 bytes long. */
|
|
||||||
unsigned long sslerror;
|
unsigned long sslerror;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
int buffsize;
|
int buffsize;
|
||||||
|
Loading…
Reference in New Issue
Block a user