@ -70,7 +70,7 @@ static int verify_peer_name_matches_certificate_name(PGconn *conn,
static void destroy_ssl_system ( void ) ;
static int initialize_SSL ( PGconn * conn ) ;
static PostgresPollingStatusType open_client_SSL ( PGconn * ) ;
static char * SSLerrmessage ( void ) ;
static char * SSLerrmessage ( unsigned long ecode ) ;
static void SSLerrfree ( char * buf ) ;
static int my_sock_read ( BIO * h , char * buf , int size ) ;
@ -152,7 +152,7 @@ pgtls_open_client(PGconn *conn)
! SSL_set_app_data ( conn - > ssl , conn ) | |
! my_SSL_set_fd ( conn , conn - > sock ) )
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not establish SSL connection: %s \n " ) ,
@ -209,11 +209,32 @@ pgtls_read(PGconn *conn, void *ptr, size_t len)
int result_errno = 0 ;
char sebuf [ 256 ] ;
int err ;
unsigned long ecode ;
rloop :
/*
* Prepare to call SSL_get_error ( ) by clearing thread ' s OpenSSL error
* queue . In general , the current thread ' s error queue must be empty
* before the TLS / SSL I / O operation is attempted , or SSL_get_error ( )
* will not work reliably . Since the possibility exists that other
* OpenSSL clients running in the same thread but not under our control
* will fail to call ERR_get_error ( ) themselves ( after their own I / O
* operations ) , pro - actively clear the per - thread error queue now .
*/
SOCK_ERRNO_SET ( 0 ) ;
ERR_clear_error ( ) ;
n = SSL_read ( conn - > ssl , ptr , len ) ;
err = SSL_get_error ( conn - > ssl , n ) ;
/*
* Other clients of OpenSSL may fail to call ERR_get_error ( ) , but we
* always do , so as to not cause problems for OpenSSL clients that
* don ' t call ERR_clear_error ( ) defensively . Be sure that this
* happens by calling now . SSL_get_error ( ) relies on the OpenSSL
* per - thread error queue being intact , so this is the earliest
* possible point ERR_get_error ( ) may be called .
*/
ecode = ( err ! = SSL_ERROR_NONE | | n < 0 ) ? ERR_get_error ( ) : 0 ;
switch ( err )
{
case SSL_ERROR_NONE :
@ -266,7 +287,7 @@ rloop:
break ;
case SSL_ERROR_SSL :
{
char * errm = SSLerrmessage ( ) ;
char * errm = SSLerrmessage ( ecode ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL error: %s \n " ) , errm ) ;
@ -318,10 +339,13 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
int result_errno = 0 ;
char sebuf [ 256 ] ;
int err ;
unsigned long ecode ;
SOCK_ERRNO_SET ( 0 ) ;
ERR_clear_error ( ) ;
n = SSL_write ( conn - > ssl , ptr , len ) ;
err = SSL_get_error ( conn - > ssl , n ) ;
ecode = ( err ! = SSL_ERROR_NONE | | n < 0 ) ? ERR_get_error ( ) : 0 ;
switch ( err )
{
case SSL_ERROR_NONE :
@ -372,7 +396,7 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
break ;
case SSL_ERROR_SSL :
{
char * errm = SSLerrmessage ( ) ;
char * errm = SSLerrmessage ( ecode ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL error: %s \n " ) , errm ) ;
@ -839,7 +863,7 @@ pgtls_init(PGconn *conn)
SSL_context = SSL_CTX_new ( SSLv23_method ( ) ) ;
if ( ! SSL_context )
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not create SSL context: %s \n " ) ,
@ -1009,7 +1033,7 @@ initialize_SSL(PGconn *conn)
# endif
if ( SSL_CTX_use_certificate_chain_file ( SSL_context , fnbuf ) ! = 1 )
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not read certificate file \" %s \" : %s \n " ) ,
@ -1024,7 +1048,7 @@ initialize_SSL(PGconn *conn)
if ( SSL_use_certificate_file ( conn - > ssl , fnbuf , SSL_FILETYPE_PEM ) ! = 1 )
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not read certificate file \" %s \" : %s \n " ) ,
@ -1079,7 +1103,7 @@ initialize_SSL(PGconn *conn)
conn - > engine = ENGINE_by_id ( engine_str ) ;
if ( conn - > engine = = NULL )
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not load SSL engine \" %s \" : %s \n " ) ,
@ -1091,7 +1115,7 @@ initialize_SSL(PGconn *conn)
if ( ENGINE_init ( conn - > engine ) = = 0 )
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not initialize SSL engine \" %s \" : %s \n " ) ,
@ -1107,7 +1131,7 @@ initialize_SSL(PGconn *conn)
NULL , NULL ) ;
if ( pkey = = NULL )
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not read private SSL key \" %s \" from engine \" %s \" : %s \n " ) ,
@ -1121,7 +1145,7 @@ initialize_SSL(PGconn *conn)
}
if ( SSL_use_PrivateKey ( conn - > ssl , pkey ) ! = 1 )
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not load private SSL key \" %s \" from engine \" %s \" : %s \n " ) ,
@ -1177,7 +1201,7 @@ initialize_SSL(PGconn *conn)
if ( SSL_use_PrivateKey_file ( conn - > ssl , fnbuf , SSL_FILETYPE_PEM ) ! = 1 )
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not load private key file \" %s \" : %s \n " ) ,
@ -1191,7 +1215,7 @@ initialize_SSL(PGconn *conn)
if ( have_cert & &
SSL_check_private_key ( conn - > ssl ) ! = 1 )
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " certificate does not match private key file \" %s \" : %s \n " ) ,
@ -1229,7 +1253,7 @@ initialize_SSL(PGconn *conn)
# endif
if ( SSL_CTX_load_verify_locations ( SSL_context , fnbuf , NULL ) ! = 1 )
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not read root certificate file \" %s \" : %s \n " ) ,
@ -1259,7 +1283,7 @@ initialize_SSL(PGconn *conn)
X509_STORE_set_flags ( cvstore ,
X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL ) ;
# else
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL library does not support CRL certificates (file \" %s \" ) \n " ) ,
@ -1327,11 +1351,14 @@ open_client_SSL(PGconn *conn)
{
int r ;
ERR_clear_error ( ) ;
r = SSL_connect ( conn - > ssl ) ;
if ( r < = 0 )
{
int err = SSL_get_error ( conn - > ssl , r ) ;
unsigned long ecode ;
ecode = ERR_get_error ( ) ;
switch ( err )
{
case SSL_ERROR_WANT_READ :
@ -1356,7 +1383,7 @@ open_client_SSL(PGconn *conn)
}
case SSL_ERROR_SSL :
{
char * err = SSLerrmessage ( ) ;
char * err = SSLerrmessage ( ecode ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL error: %s \n " ) ,
@ -1384,7 +1411,9 @@ open_client_SSL(PGconn *conn)
conn - > peer = SSL_get_peer_certificate ( conn - > ssl ) ;
if ( conn - > peer = = NULL )
{
char * err = SSLerrmessage ( ) ;
char * err ;
err = SSLerrmessage ( ERR_get_error ( ) ) ;
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " certificate could not be obtained: %s \n " ) ,
@ -1456,7 +1485,9 @@ pgtls_close(PGconn *conn)
/*
* Obtain reason string for last SSL error
* Obtain reason string for passed SSL errcode
*
* ERR_get_error ( ) is used by caller to get errcode to pass here .
*
* Some caution is needed here since ERR_reason_error_string will
* return NULL if it doesn ' t recognize the error code . We don ' t
@ -1467,28 +1498,26 @@ static char ssl_nomem[] = "out of memory allocating error description";
# define SSL_ERR_LEN 128
static char *
SSLerrmessage ( void )
SSLerrmessage ( unsigned long ecode )
{
unsigned long errcode ;
const char * errreason ;
char * errbuf ;
errbuf = malloc ( SSL_ERR_LEN ) ;
if ( ! errbuf )
return ssl_nomem ;
errcode = ERR_get_error ( ) ;
if ( errcode = = 0 )
if ( ecode = = 0 )
{
snprintf ( errbuf , SSL_ERR_LEN , libpq_gettext ( " no SSL error reported " ) ) ;
return errbuf ;
}
errreason = ERR_reason_error_string ( err code ) ;
errreason = ERR_reason_error_string ( ecode ) ;
if ( errreason ! = NULL )
{
strlcpy ( errbuf , errreason , SSL_ERR_LEN ) ;
return errbuf ;
}
snprintf ( errbuf , SSL_ERR_LEN , libpq_gettext ( " SSL error code %lu " ) , err code ) ;
snprintf ( errbuf , SSL_ERR_LEN , libpq_gettext ( " SSL error code %lu " ) , ecode ) ;
return errbuf ;
}