#include "postgres_fe.h"#include <signal.h>#include <fcntl.h>#include <ctype.h>#include "libpq-fe.h"#include "fe-auth.h"#include "libpq-int.h"#include <sys/socket.h>#include <unistd.h>#include <netdb.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/stat.h>
Go to the source code of this file.
Defines | |
| #define | SIGPIPE_MASKED(conn) ((conn)->sigpipe_so || (conn)->sigpipe_flag) |
| #define | DECLARE_SIGPIPE_INFO(spinfo) pqsigfunc spinfo = NULL |
| #define | DISABLE_SIGPIPE(conn, spinfo, failaction) |
| #define | REMEMBER_EPIPE(spinfo, cond) |
| #define | RESTORE_SIGPIPE(conn, spinfo) |
Functions | |
| void | PQinitSSL (int do_init) |
| void | PQinitOpenSSL (int do_ssl, int do_crypto) |
| int | pqsecure_initialize (PGconn *conn) |
| void | pqsecure_destroy (void) |
| PostgresPollingStatusType | pqsecure_open_client (PGconn *conn) |
| void | pqsecure_close (PGconn *conn) |
| ssize_t | pqsecure_read (PGconn *conn, void *ptr, size_t len) |
| ssize_t | pqsecure_write (PGconn *conn, const void *ptr, size_t len) |
| void * | PQgetssl (PGconn *conn) |
| #define DECLARE_SIGPIPE_INFO | ( | spinfo | ) | pqsigfunc spinfo = NULL |
Definition at line 155 of file fe-secure.c.
Referenced by pqsecure_read(), and pqsecure_write().
| #define DISABLE_SIGPIPE | ( | conn, | ||
| spinfo, | ||||
| failaction | ||||
| ) |
do { \ if (!SIGPIPE_MASKED(conn)) \ spinfo = pqsignal(SIGPIPE, SIG_IGN); \ } while (0)
Definition at line 157 of file fe-secure.c.
Referenced by pqsecure_read(), and pqsecure_write().
| #define REMEMBER_EPIPE | ( | spinfo, | ||
| cond | ||||
| ) |
Definition at line 163 of file fe-secure.c.
Referenced by pqsecure_read(), and pqsecure_write().
| #define RESTORE_SIGPIPE | ( | conn, | ||
| spinfo | ||||
| ) |
do { \ if (!SIGPIPE_MASKED(conn)) \ pqsignal(SIGPIPE, spinfo); \ } while (0)
Definition at line 165 of file fe-secure.c.
Referenced by pqsecure_read(), and pqsecure_write().
Definition at line 117 of file fe-secure.c.
| void* PQgetssl | ( | PGconn * | conn | ) |
| void PQinitOpenSSL | ( | int | do_ssl, | |
| int | do_crypto | |||
| ) |
Definition at line 199 of file fe-secure.c.
Referenced by PQinitSSL().
{
#ifdef USE_SSL
#ifdef ENABLE_THREAD_SAFETY
/*
* Disallow changing the flags while we have open connections, else we'd
* get completely confused.
*/
if (ssl_open_connections != 0)
return;
#endif
pq_init_ssl_lib = do_ssl;
pq_init_crypto_lib = do_crypto;
#endif
}
| void PQinitSSL | ( | int | do_init | ) |
Definition at line 189 of file fe-secure.c.
References PQinitOpenSSL().
{
PQinitOpenSSL(do_init, do_init);
}
| void pqsecure_close | ( | PGconn * | conn | ) |
Definition at line 294 of file fe-secure.c.
Referenced by pqDropConnection().
{
#ifdef USE_SSL
if (conn->ssl)
close_SSL(conn);
#endif
}
| void pqsecure_destroy | ( | void | ) |
Definition at line 236 of file fe-secure.c.
{
#ifdef USE_SSL
destroySSL();
#endif
}
| int pqsecure_initialize | ( | PGconn * | conn | ) |
Definition at line 221 of file fe-secure.c.
Referenced by PQconnectPoll().
{
int r = 0;
#ifdef USE_SSL
r = init_ssl_system(conn);
#endif
return r;
}
| PostgresPollingStatusType pqsecure_open_client | ( | PGconn * | conn | ) |
Definition at line 247 of file fe-secure.c.
References pg_conn::errorMessage, libpq_gettext, NULL, printfPQExpBuffer(), pg_conn::sigpipe_flag, and pg_conn::sock.
Referenced by PQconnectPoll().
{
#ifdef USE_SSL
/* First time through? */
if (conn->ssl == NULL)
{
/* We cannot use MSG_NOSIGNAL to block SIGPIPE when using SSL */
conn->sigpipe_flag = false;
/* Create a connection-specific SSL object */
if (!(conn->ssl = SSL_new(SSL_context)) ||
!SSL_set_app_data(conn->ssl, conn) ||
!SSL_set_fd(conn->ssl, conn->sock))
{
char *err = SSLerrmessage();
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not establish SSL connection: %s\n"),
err);
SSLerrfree(err);
close_SSL(conn);
return PGRES_POLLING_FAILED;
}
/*
* Load client certificate, private key, and trusted CA certs.
*/
if (initialize_SSL(conn) != 0)
{
/* initialize_SSL already put a message in conn->errorMessage */
close_SSL(conn);
return PGRES_POLLING_FAILED;
}
}
/* Begin or continue the actual handshake */
return open_client_SSL(conn);
#else
/* shouldn't get here */
return PGRES_POLLING_FAILED;
#endif
}
| ssize_t pqsecure_read | ( | PGconn * | conn, | |
| void * | ptr, | |||
| size_t | len | |||
| ) |
Definition at line 310 of file fe-secure.c.
References DECLARE_SIGPIPE_INFO, DISABLE_SIGPIPE, EAGAIN, ECONNRESET, EINTR, pg_conn::errorMessage, EWOULDBLOCK, libpq_gettext, printfPQExpBuffer(), recv, REMEMBER_EPIPE, RESTORE_SIGPIPE, pg_conn::sock, SOCK_ERRNO_SET, and SOCK_STRERROR.
Referenced by pqReadData().
{
ssize_t n;
int result_errno = 0;
char sebuf[256];
#ifdef USE_SSL
if (conn->ssl)
{
int err;
DECLARE_SIGPIPE_INFO(spinfo);
/* SSL_read can write to the socket, so we need to disable SIGPIPE */
DISABLE_SIGPIPE(conn, spinfo, return -1);
rloop:
SOCK_ERRNO_SET(0);
n = SSL_read(conn->ssl, ptr, len);
err = SSL_get_error(conn->ssl, n);
switch (err)
{
case SSL_ERROR_NONE:
if (n < 0)
{
/* Not supposed to happen, so we don't translate the msg */
printfPQExpBuffer(&conn->errorMessage,
"SSL_read failed but did not provide error information\n");
/* assume the connection is broken */
result_errno = ECONNRESET;
}
break;
case SSL_ERROR_WANT_READ:
n = 0;
break;
case SSL_ERROR_WANT_WRITE:
/*
* Returning 0 here would cause caller to wait for read-ready,
* which is not correct since what SSL wants is wait for
* write-ready. The former could get us stuck in an infinite
* wait, so don't risk it; busy-loop instead.
*/
goto rloop;
case SSL_ERROR_SYSCALL:
if (n < 0)
{
result_errno = SOCK_ERRNO;
REMEMBER_EPIPE(spinfo, result_errno == EPIPE);
if (result_errno == EPIPE ||
result_errno == ECONNRESET)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext(
"server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
else
printfPQExpBuffer(&conn->errorMessage,
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();
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), errm);
SSLerrfree(errm);
/* assume the connection is broken */
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"));
result_errno = ECONNRESET;
n = -1;
break;
default:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("unrecognized SSL error code: %d\n"),
err);
/* assume the connection is broken */
result_errno = ECONNRESET;
n = -1;
break;
}
RESTORE_SIGPIPE(conn, spinfo);
}
else
#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"
"\tThis probably means the server terminated abnormally\n"
"\tbefore 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;
}
| ssize_t pqsecure_write | ( | PGconn * | conn, | |
| const void * | ptr, | |||
| size_t | len | |||
| ) |
Definition at line 473 of file fe-secure.c.
References DECLARE_SIGPIPE_INFO, DISABLE_SIGPIPE, EAGAIN, ECONNRESET, EINTR, pg_conn::errorMessage, EWOULDBLOCK, libpq_gettext, printfPQExpBuffer(), REMEMBER_EPIPE, RESTORE_SIGPIPE, send, pg_conn::sigpipe_flag, pg_conn::sock, SOCK_ERRNO_SET, and SOCK_STRERROR.
Referenced by pqSendSome().
{
ssize_t n;
int result_errno = 0;
char sebuf[256];
DECLARE_SIGPIPE_INFO(spinfo);
#ifdef USE_SSL
if (conn->ssl)
{
int err;
DISABLE_SIGPIPE(conn, spinfo, return -1);
SOCK_ERRNO_SET(0);
n = SSL_write(conn->ssl, ptr, len);
err = SSL_get_error(conn->ssl, n);
switch (err)
{
case SSL_ERROR_NONE:
if (n < 0)
{
/* Not supposed to happen, so we don't translate the msg */
printfPQExpBuffer(&conn->errorMessage,
"SSL_write failed but did not provide error information\n");
/* assume the connection is broken */
result_errno = ECONNRESET;
}
break;
case SSL_ERROR_WANT_READ:
/*
* Returning 0 here causes caller to wait for write-ready,
* which is not really the right thing, but it's the best we
* can do.
*/
n = 0;
break;
case SSL_ERROR_WANT_WRITE:
n = 0;
break;
case SSL_ERROR_SYSCALL:
if (n < 0)
{
result_errno = SOCK_ERRNO;
REMEMBER_EPIPE(spinfo, result_errno == EPIPE);
if (result_errno == EPIPE ||
result_errno == ECONNRESET)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext(
"server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
else
printfPQExpBuffer(&conn->errorMessage,
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();
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), errm);
SSLerrfree(errm);
/* assume the connection is broken */
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"));
result_errno = ECONNRESET;
n = -1;
break;
default:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("unrecognized SSL error code: %d\n"),
err);
/* assume the connection is broken */
result_errno = ECONNRESET;
n = -1;
break;
}
}
else
#endif /* USE_SSL */
{
int flags = 0;
#ifdef MSG_NOSIGNAL
if (conn->sigpipe_flag)
flags |= MSG_NOSIGNAL;
retry_masked:
#endif /* MSG_NOSIGNAL */
DISABLE_SIGPIPE(conn, spinfo, return -1);
n = send(conn->sock, ptr, len, flags);
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 && result_errno == EINVAL)
{
conn->sigpipe_flag = false;
flags = 0;
goto retry_masked;
}
#endif /* MSG_NOSIGNAL */
/* 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"
"\tThis probably means the server terminated abnormally\n"
"\tbefore 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;
}
1.7.1