@ -303,15 +303,16 @@ pqsecure_close(PGconn *conn)
/*
* Read data from a secure connection .
*
* If SSL is in use , this function is responsible for putting a suitable
* message into conn - > errorMessage upon error ; but the caller does that
* when not using SSL . In either case , caller uses the returned errno
* to decide whether to continue / retry after error .
* On failure , this function is responsible for putting a suitable message
* into conn - > errorMessage . The caller must still inspect errno , but only
* to determine whether to continue / retry after error .
*/
ssize_t
pqsecure_read ( PGconn * conn , void * ptr , size_t len )
{
ssize_t n ;
int result_errno = 0 ;
char sebuf [ 256 ] ;
# ifdef USE_SSL
if ( conn - > ssl )
@ -332,10 +333,11 @@ rloop:
case SSL_ERROR_NONE :
if ( n < 0 )
{
/* Not supposed to happen, so we don't translate the msg */
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL_read failed but did not provide error information \n " ) ) ;
" SSL_read failed but did not provide error information \n " ) ;
/* assume the connection is broken */
SOCK_ERRNO_SET ( ECONNRESET ) ;
result_errno = ECONNRESET ;
}
break ;
case SSL_ERROR_WANT_READ :
@ -351,26 +353,32 @@ rloop:
*/
goto rloop ;
case SSL_ERROR_SYSCALL :
if ( n < 0 )
{
char sebuf [ 256 ] ;
if ( n < 0 )
{
REMEMBER_EPIPE ( spinfo , SOCK_ERRNO = = EPIPE ) ;
result_errno = SOCK_ERRNO ;
REMEMBER_EPIPE ( spinfo , result_errno = = EPIPE ) ;
if ( result_errno = = EPIPE | |
result_errno = = ECONNRESET )
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL SYSCALL error: %s \n " ) ,
SOCK_STRERROR ( SOCK_ERRNO , sebuf , sizeof ( sebuf ) ) ) ;
}
libpq_gettext (
" server closed the connection unexpectedly \n "
" \t This probably means the server terminated abnormally \n "
" \t before or while processing the request. \n " ) ) ;
else
{
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL SYSCALL error: EOF detected \n " ) ) ;
/* assume the connection is broken */
SOCK_ERRNO_SET ( ECONNRESET ) ;
n = - 1 ;
}
break ;
libpq_gettext ( " SSL SYSCALL error: %s \n " ) ,
SOCK_STRERROR ( result_errno ,
sebuf , sizeof ( sebuf ) ) ) ;
}
else
{
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL SYSCALL error: EOF detected \n " ) ) ;
/* assume the connection is broken */
result_errno = ECONNRESET ;
n = - 1 ;
}
break ;
case SSL_ERROR_SSL :
{
char * errm = SSLerrmessage ( ) ;
@ -379,14 +387,19 @@ rloop:
libpq_gettext ( " SSL error: %s \n " ) , errm ) ;
SSLerrfree ( errm ) ;
/* assume the connection is broken */
SOCK_ERRNO_SET ( ECONNRESET ) ;
result_errno = ECONNRESET ;
n = - 1 ;
break ;
}
case SSL_ERROR_ZERO_RETURN :
/*
* Per OpenSSL documentation , this error code is only returned
* for a clean connection closure , so we should not report it
* as a server crash .
*/
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL connection has been closed unexpectedly \n " ) ) ;
SOCK_ERRNO_SET ( ECONNRESET ) ;
result_errno = ECONNRESET ;
n = - 1 ;
break ;
default :
@ -394,7 +407,7 @@ rloop:
libpq_gettext ( " unrecognized SSL error code: %d \n " ) ,
err ) ;
/* assume the connection is broken */
SOCK_ERRNO_SET ( ECONNRESET ) ;
result_errno = ECONNRESET ;
n = - 1 ;
break ;
}
@ -402,24 +415,66 @@ rloop:
RESTORE_SIGPIPE ( conn , spinfo ) ;
}
else
# endif
# endif /* USE_SSL */
{
n = recv ( conn - > sock , ptr , len , 0 ) ;
if ( n < 0 )
{
result_errno = SOCK_ERRNO ;
/* Set error message if appropriate */
switch ( result_errno )
{
# ifdef EAGAIN
case EAGAIN :
# endif
# if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
case EWOULDBLOCK :
# endif
case EINTR :
/* no error message, caller is expected to retry */
break ;
# ifdef ECONNRESET
case ECONNRESET :
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext (
" server closed the connection unexpectedly \n "
" \t This probably means the server terminated abnormally \n "
" \t before or while processing the request. \n " ) ) ;
break ;
# endif
default :
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not receive data from server: %s \n " ) ,
SOCK_STRERROR ( result_errno ,
sebuf , sizeof ( sebuf ) ) ) ;
break ;
}
}
}
/* ensure we return the intended errno to caller */
SOCK_ERRNO_SET ( result_errno ) ;
return n ;
}
/*
* Write data to a secure connection .
*
* If SSL is in use , this function is responsible for putting a suitable
* message into conn - > errorMessage upon error ; but the caller does that
* when not using SSL . In either case , caller uses the returned errno
* to decide whether to continue / retry after error .
* On failure , this function is responsible for putting a suitable message
* into conn - > errorMessage . The caller must still inspect errno , but only
* to determine whether to continue / retry after error .
*/
ssize_t
pqsecure_write ( PGconn * conn , const void * ptr , size_t len )
{
ssize_t n ;
int result_errno = 0 ;
char sebuf [ 256 ] ;
DECLARE_SIGPIPE_INFO ( spinfo ) ;
@ -438,10 +493,11 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
case SSL_ERROR_NONE :
if ( n < 0 )
{
/* Not supposed to happen, so we don't translate the msg */
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL_write failed but did not provide error information \n " ) ) ;
" SSL_write failed but did not provide error information \n " ) ;
/* assume the connection is broken */
SOCK_ERRNO_SET ( ECONNRESET ) ;
result_errno = ECONNRESET ;
}
break ;
case SSL_ERROR_WANT_READ :
@ -457,26 +513,32 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
n = 0 ;
break ;
case SSL_ERROR_SYSCALL :
if ( n < 0 )
{
char sebuf [ 256 ] ;
if ( n < 0 )
{
REMEMBER_EPIPE ( spinfo , SOCK_ERRNO = = EPIPE ) ;
result_errno = SOCK_ERRNO ;
REMEMBER_EPIPE ( spinfo , result_errno = = EPIPE ) ;
if ( result_errno = = EPIPE | |
result_errno = = ECONNRESET )
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL SYSCALL error: %s \n " ) ,
SOCK_STRERROR ( SOCK_ERRNO , sebuf , sizeof ( sebuf ) ) ) ;
}
libpq_gettext (
" server closed the connection unexpectedly \n "
" \t This probably means the server terminated abnormally \n "
" \t before or while processing the request. \n " ) ) ;
else
{
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL SYSCALL error: EOF detected \n " ) ) ;
/* assume the connection is broken */
SOCK_ERRNO_SET ( ECONNRESET ) ;
n = - 1 ;
}
break ;
libpq_gettext ( " SSL SYSCALL error: %s \n " ) ,
SOCK_STRERROR ( result_errno ,
sebuf , sizeof ( sebuf ) ) ) ;
}
else
{
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL SYSCALL error: EOF detected \n " ) ) ;
/* assume the connection is broken */
result_errno = ECONNRESET ;
n = - 1 ;
}
break ;
case SSL_ERROR_SSL :
{
char * errm = SSLerrmessage ( ) ;
@ -485,14 +547,19 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
libpq_gettext ( " SSL error: %s \n " ) , errm ) ;
SSLerrfree ( errm ) ;
/* assume the connection is broken */
SOCK_ERRNO_SET ( ECONNRESET ) ;
result_errno = ECONNRESET ;
n = - 1 ;
break ;
}
case SSL_ERROR_ZERO_RETURN :
/*
* Per OpenSSL documentation , this error code is only returned
* for a clean connection closure , so we should not report it
* as a server crash .
*/
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " SSL connection has been closed unexpectedly \n " ) ) ;
SOCK_ERRNO_SET ( ECONNRESET ) ;
result_errno = ECONNRESET ;
n = - 1 ;
break ;
default :
@ -500,13 +567,13 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
libpq_gettext ( " unrecognized SSL error code: %d \n " ) ,
err ) ;
/* assume the connection is broken */
SOCK_ERRNO_SET ( ECONNRESET ) ;
result_errno = ECONNRESET ;
n = - 1 ;
break ;
}
}
else
# endif
# endif /* USE_SSL */
{
int flags = 0 ;
@ -523,13 +590,15 @@ retry_masked:
if ( n < 0 )
{
result_errno = SOCK_ERRNO ;
/*
* If we see an EINVAL , it may be because MSG_NOSIGNAL isn ' t
* available on this machine . So , clear sigpipe_flag so we don ' t
* try the flag again , and retry the send ( ) .
*/
# ifdef MSG_NOSIGNAL
if ( flags ! = 0 & & SOCK_ERRNO = = EINVAL )
if ( flags ! = 0 & & result_errno = = EINVAL )
{
conn - > sigpipe_flag = false ;
flags = 0 ;
@ -537,12 +606,49 @@ retry_masked:
}
# endif /* MSG_NOSIGNAL */
REMEMBER_EPIPE ( spinfo , SOCK_ERRNO = = EPIPE ) ;
/* Set error message if appropriate */
switch ( result_errno )
{
# ifdef EAGAIN
case EAGAIN :
# endif
# if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
case EWOULDBLOCK :
# endif
case EINTR :
/* no error message, caller is expected to retry */
break ;
case EPIPE :
/* Set flag for EPIPE */
REMEMBER_EPIPE ( spinfo , true ) ;
/* FALL THRU */
# ifdef ECONNRESET
case ECONNRESET :
# endif
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext (
" server closed the connection unexpectedly \n "
" \t This probably means the server terminated abnormally \n "
" \t before or while processing the request. \n " ) ) ;
break ;
default :
printfPQExpBuffer ( & conn - > errorMessage ,
libpq_gettext ( " could not send data to server: %s \n " ) ,
SOCK_STRERROR ( result_errno ,
sebuf , sizeof ( sebuf ) ) ) ;
break ;
}
}
}
RESTORE_SIGPIPE ( conn , spinfo ) ;
/* ensure we return the intended errno to caller */
SOCK_ERRNO_SET ( result_errno ) ;
return n ;
}