PostgreSQL Source Code  git master
fe-secure.c File Reference
#include "postgres_fe.h"
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <pthread.h>
#include "fe-auth.h"
#include "libpq-fe.h"
#include "libpq-int.h"
Include dependency graph for fe-secure.c:

Go to the source code of this file.

Data Structures

struct  sigpipe_info
 

Macros

#define SIGPIPE_MASKED(conn)   ((conn)->sigpipe_so || (conn)->sigpipe_flag)
 
#define DECLARE_SIGPIPE_INFO(spinfo)   struct sigpipe_info spinfo
 
#define DISABLE_SIGPIPE(conn, spinfo, failaction)
 
#define REMEMBER_EPIPE(spinfo, cond)
 
#define RESTORE_SIGPIPE(conn, spinfo)
 

Functions

int PQsslInUse (PGconn *conn)
 
void PQinitSSL (int do_init)
 
void PQinitOpenSSL (int do_ssl, int do_crypto)
 
int pqsecure_initialize (PGconn *conn, bool do_ssl, bool do_crypto)
 
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_raw_read (PGconn *conn, void *ptr, size_t len)
 
ssize_t pqsecure_write (PGconn *conn, const void *ptr, size_t len)
 
ssize_t pqsecure_raw_write (PGconn *conn, const void *ptr, size_t len)
 
void * PQgetssl (PGconn *conn)
 
void * PQsslStruct (PGconn *conn, const char *struct_name)
 
const char * PQsslAttribute (PGconn *conn, const char *attribute_name)
 
const char *const * PQsslAttributeNames (PGconn *conn)
 
PQsslKeyPassHook_OpenSSL_type PQgetSSLKeyPassHook_OpenSSL (void)
 
void PQsetSSLKeyPassHook_OpenSSL (PQsslKeyPassHook_OpenSSL_type hook)
 
int PQdefaultSSLKeyPassHook_OpenSSL (char *buf, int size, PGconn *conn)
 
void * PQgetgssctx (PGconn *conn)
 
int PQgssEncInUse (PGconn *conn)
 
int pq_block_sigpipe (sigset_t *osigset, bool *sigpipe_pending)
 
void pq_reset_sigpipe (sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
 

Macro Definition Documentation

◆ DECLARE_SIGPIPE_INFO

#define DECLARE_SIGPIPE_INFO (   spinfo)    struct sigpipe_info spinfo

Definition at line 64 of file fe-secure.c.

◆ DISABLE_SIGPIPE

#define DISABLE_SIGPIPE (   conn,
  spinfo,
  failaction 
)
Value:
do { \
(spinfo).got_epipe = false; \
{ \
if (pq_block_sigpipe(&(spinfo).oldsigmask, \
&(spinfo).sigpipe_pending) < 0) \
failaction; \
} \
} while (0)
#define SIGPIPE_MASKED(conn)
Definition: fe-secure.c:55
int pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
Definition: fe-secure.c:512
PGconn * conn
Definition: streamutil.c:54

Definition at line 66 of file fe-secure.c.

◆ REMEMBER_EPIPE

#define REMEMBER_EPIPE (   spinfo,
  cond 
)
Value:
do { \
if (cond) \
(spinfo).got_epipe = true; \
} while (0)

Definition at line 77 of file fe-secure.c.

◆ RESTORE_SIGPIPE

#define RESTORE_SIGPIPE (   conn,
  spinfo 
)
Value:
do { \
pq_reset_sigpipe(&(spinfo).oldsigmask, (spinfo).sigpipe_pending, \
(spinfo).got_epipe); \
} while (0)

Definition at line 83 of file fe-secure.c.

◆ SIGPIPE_MASKED

#define SIGPIPE_MASKED (   conn)    ((conn)->sigpipe_so || (conn)->sigpipe_flag)

Definition at line 55 of file fe-secure.c.

Function Documentation

◆ pq_block_sigpipe()

int pq_block_sigpipe ( sigset_t *  osigset,
bool sigpipe_pending 
)

Definition at line 512 of file fe-secure.c.

513 {
514  sigset_t sigpipe_sigset;
515  sigset_t sigset;
516 
517  sigemptyset(&sigpipe_sigset);
518  sigaddset(&sigpipe_sigset, SIGPIPE);
519 
520  /* Block SIGPIPE and save previous mask for later reset */
521  SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
522  if (SOCK_ERRNO)
523  return -1;
524 
525  /* We can have a pending SIGPIPE only if it was blocked before */
526  if (sigismember(osigset, SIGPIPE))
527  {
528  /* Is there a pending SIGPIPE? */
529  if (sigpending(&sigset) != 0)
530  return -1;
531 
532  if (sigismember(&sigset, SIGPIPE))
533  *sigpipe_pending = true;
534  else
535  *sigpipe_pending = false;
536  }
537  else
538  *sigpipe_pending = false;
539 
540  return 0;
541 }
#define SOCK_ERRNO
Definition: libpq-int.h:921
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:923
#define SIGPIPE
Definition: win32_port.h:173

References SIGPIPE, SOCK_ERRNO, and SOCK_ERRNO_SET.

Referenced by PQprint().

◆ pq_reset_sigpipe()

void pq_reset_sigpipe ( sigset_t *  osigset,
bool  sigpipe_pending,
bool  got_epipe 
)

Definition at line 562 of file fe-secure.c.

563 {
564  int save_errno = SOCK_ERRNO;
565  int signo;
566  sigset_t sigset;
567 
568  /* Clear SIGPIPE only if none was pending */
569  if (got_epipe && !sigpipe_pending)
570  {
571  if (sigpending(&sigset) == 0 &&
572  sigismember(&sigset, SIGPIPE))
573  {
574  sigset_t sigpipe_sigset;
575 
576  sigemptyset(&sigpipe_sigset);
577  sigaddset(&sigpipe_sigset, SIGPIPE);
578 
579  sigwait(&sigpipe_sigset, &signo);
580  }
581  }
582 
583  /* Restore saved block mask */
584  pthread_sigmask(SIG_SETMASK, osigset, NULL);
585 
586  SOCK_ERRNO_SET(save_errno);
587 }

References SIGPIPE, SOCK_ERRNO, and SOCK_ERRNO_SET.

Referenced by PQprint().

◆ PQdefaultSSLKeyPassHook_OpenSSL()

int PQdefaultSSLKeyPassHook_OpenSSL ( char *  buf,
int  size,
PGconn conn 
)

Definition at line 481 of file fe-secure.c.

482 {
483  return 0;
484 }

◆ PQgetgssctx()

void* PQgetgssctx ( PGconn conn)

Definition at line 491 of file fe-secure.c.

492 {
493  return NULL;
494 }

◆ PQgetssl()

void* PQgetssl ( PGconn conn)

Definition at line 436 of file fe-secure.c.

437 {
438  return NULL;
439 }

◆ PQgetSSLKeyPassHook_OpenSSL()

PQsslKeyPassHook_OpenSSL_type PQgetSSLKeyPassHook_OpenSSL ( void  )

Definition at line 469 of file fe-secure.c.

470 {
471  return NULL;
472 }

◆ PQgssEncInUse()

int PQgssEncInUse ( PGconn conn)

Definition at line 497 of file fe-secure.c.

498 {
499  return 0;
500 }

◆ PQinitOpenSSL()

void PQinitOpenSSL ( int  do_ssl,
int  do_crypto 
)

Definition at line 127 of file fe-secure.c.

128 {
129 #ifdef USE_SSL
130  pgtls_init_library(do_ssl, do_crypto);
131 #endif
132 }
void pgtls_init_library(bool do_ssl, int do_crypto)

References pgtls_init_library().

◆ PQinitSSL()

void PQinitSSL ( int  do_init)

Definition at line 115 of file fe-secure.c.

116 {
117 #ifdef USE_SSL
119 #endif
120 }
static void do_init(void)
Definition: pg_ctl.c:894

References do_init(), and pgtls_init_library().

◆ pqsecure_close()

void pqsecure_close ( PGconn conn)

Definition at line 167 of file fe-secure.c.

168 {
169 #ifdef USE_SSL
170  pgtls_close(conn);
171 #endif
172 }
void pgtls_close(PGconn *conn)

References conn, and pgtls_close().

Referenced by pqDropConnection().

◆ pqsecure_initialize()

int pqsecure_initialize ( PGconn conn,
bool  do_ssl,
bool  do_crypto 
)

Definition at line 138 of file fe-secure.c.

139 {
140  int r = 0;
141 
142 #ifdef USE_SSL
143  r = pgtls_init(conn, do_ssl, do_crypto);
144 #endif
145 
146  return r;
147 }
int pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)

References conn, and pgtls_init().

Referenced by PQconnectPoll().

◆ pqsecure_open_client()

PostgresPollingStatusType pqsecure_open_client ( PGconn conn)

Definition at line 153 of file fe-secure.c.

154 {
155 #ifdef USE_SSL
156  return pgtls_open_client(conn);
157 #else
158  /* shouldn't get here */
159  return PGRES_POLLING_FAILED;
160 #endif
161 }
PostgresPollingStatusType pgtls_open_client(PGconn *conn)
@ PGRES_POLLING_FAILED
Definition: libpq-fe.h:86

References conn, PGRES_POLLING_FAILED, and pgtls_open_client().

Referenced by PQconnectPoll().

◆ pqsecure_raw_read()

ssize_t pqsecure_raw_read ( PGconn conn,
void *  ptr,
size_t  len 
)

Definition at line 208 of file fe-secure.c.

209 {
210  ssize_t n;
211  int result_errno = 0;
212  char sebuf[PG_STRERROR_R_BUFLEN];
213 
214  n = recv(conn->sock, ptr, len, 0);
215 
216  if (n < 0)
217  {
218  result_errno = SOCK_ERRNO;
219 
220  /* Set error message if appropriate */
221  switch (result_errno)
222  {
223 #ifdef EAGAIN
224  case EAGAIN:
225 #endif
226 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
227  case EWOULDBLOCK:
228 #endif
229  case EINTR:
230  /* no error message, caller is expected to retry */
231  break;
232 
233  case EPIPE:
234  case ECONNRESET:
235  libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
236  "\tThis probably means the server terminated abnormally\n"
237  "\tbefore or while processing the request.");
238  break;
239 
240  default:
241  libpq_append_conn_error(conn, "could not receive data from server: %s",
242  SOCK_STRERROR(result_errno,
243  sebuf, sizeof(sebuf)));
244  break;
245  }
246  }
247 
248  /* ensure we return the intended errno to caller */
249  SOCK_ERRNO_SET(result_errno);
250 
251  return n;
252 }
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1312
#define SOCK_STRERROR
Definition: libpq-int.h:922
const void size_t len
#define PG_STRERROR_R_BUFLEN
Definition: port.h:256
pgsocket sock
Definition: libpq-int.h:459
#define EINTR
Definition: win32_port.h:374
#define EWOULDBLOCK
Definition: win32_port.h:380
#define recv(s, buf, len, flags)
Definition: win32_port.h:496
#define ECONNRESET
Definition: win32_port.h:384
#define EAGAIN
Definition: win32_port.h:372

References conn, EAGAIN, ECONNRESET, EINTR, EWOULDBLOCK, len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, recv, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, and SOCK_STRERROR.

Referenced by gss_read(), my_sock_read(), pg_GSS_read(), and pqsecure_read().

◆ pqsecure_raw_write()

ssize_t pqsecure_raw_write ( PGconn conn,
const void *  ptr,
size_t  len 
)

Definition at line 324 of file fe-secure.c.

325 {
326  ssize_t n;
327  int flags = 0;
328  int result_errno = 0;
329  char msgbuf[1024];
330  char sebuf[PG_STRERROR_R_BUFLEN];
331 
332  DECLARE_SIGPIPE_INFO(spinfo);
333 
334  /*
335  * If we already had a write failure, we will never again try to send data
336  * on that connection. Even if the kernel would let us, we've probably
337  * lost message boundary sync with the server. conn->write_failed
338  * therefore persists until the connection is reset, and we just discard
339  * all data presented to be written.
340  */
341  if (conn->write_failed)
342  return len;
343 
344 #ifdef MSG_NOSIGNAL
345  if (conn->sigpipe_flag)
346  flags |= MSG_NOSIGNAL;
347 
348 retry_masked:
349 #endif /* MSG_NOSIGNAL */
350 
351  DISABLE_SIGPIPE(conn, spinfo, return -1);
352 
353  n = send(conn->sock, ptr, len, flags);
354 
355  if (n < 0)
356  {
357  result_errno = SOCK_ERRNO;
358 
359  /*
360  * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
361  * on this machine. So, clear sigpipe_flag so we don't try the flag
362  * again, and retry the send().
363  */
364 #ifdef MSG_NOSIGNAL
365  if (flags != 0 && result_errno == EINVAL)
366  {
367  conn->sigpipe_flag = false;
368  flags = 0;
369  goto retry_masked;
370  }
371 #endif /* MSG_NOSIGNAL */
372 
373  /* Set error message if appropriate */
374  switch (result_errno)
375  {
376 #ifdef EAGAIN
377  case EAGAIN:
378 #endif
379 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
380  case EWOULDBLOCK:
381 #endif
382  case EINTR:
383  /* no error message, caller is expected to retry */
384  break;
385 
386  case EPIPE:
387  /* Set flag for EPIPE */
388  REMEMBER_EPIPE(spinfo, true);
389 
390  /* FALL THRU */
391 
392  case ECONNRESET:
393  conn->write_failed = true;
394  /* Store error message in conn->write_err_msg, if possible */
395  /* (strdup failure is OK, we'll cope later) */
396  snprintf(msgbuf, sizeof(msgbuf),
397  libpq_gettext("server closed the connection unexpectedly\n"
398  "\tThis probably means the server terminated abnormally\n"
399  "\tbefore or while processing the request."));
400  /* keep newline out of translated string */
401  strlcat(msgbuf, "\n", sizeof(msgbuf));
402  conn->write_err_msg = strdup(msgbuf);
403  /* Now claim the write succeeded */
404  n = len;
405  break;
406 
407  default:
408  conn->write_failed = true;
409  /* Store error message in conn->write_err_msg, if possible */
410  /* (strdup failure is OK, we'll cope later) */
411  snprintf(msgbuf, sizeof(msgbuf),
412  libpq_gettext("could not send data to server: %s"),
413  SOCK_STRERROR(result_errno,
414  sebuf, sizeof(sebuf)));
415  /* keep newline out of translated string */
416  strlcat(msgbuf, "\n", sizeof(msgbuf));
417  conn->write_err_msg = strdup(msgbuf);
418  /* Now claim the write succeeded */
419  n = len;
420  break;
421  }
422  }
423 
424  RESTORE_SIGPIPE(conn, spinfo);
425 
426  /* ensure we return the intended errno to caller */
427  SOCK_ERRNO_SET(result_errno);
428 
429  return n;
430 }
#define REMEMBER_EPIPE(spinfo, cond)
Definition: fe-secure.c:77
#define DISABLE_SIGPIPE(conn, spinfo, failaction)
Definition: fe-secure.c:66
#define DECLARE_SIGPIPE_INFO(spinfo)
Definition: fe-secure.c:64
#define RESTORE_SIGPIPE(conn, spinfo)
Definition: fe-secure.c:83
#define libpq_gettext(x)
Definition: libpq-int.h:900
#define snprintf
Definition: port.h:238
size_t strlcat(char *dst, const char *src, size_t siz)
Definition: strlcat.c:33
char * write_err_msg
Definition: libpq-int.h:471
bool sigpipe_flag
Definition: libpq-int.h:469
bool write_failed
Definition: libpq-int.h:470
#define send(s, buf, len, flags)
Definition: win32_port.h:497

References conn, DECLARE_SIGPIPE_INFO, DISABLE_SIGPIPE, EAGAIN, ECONNRESET, EINTR, EWOULDBLOCK, len, libpq_gettext, PG_STRERROR_R_BUFLEN, REMEMBER_EPIPE, RESTORE_SIGPIPE, send, pg_conn::sigpipe_flag, snprintf, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, strlcat(), pg_conn::write_err_msg, and pg_conn::write_failed.

Referenced by my_sock_write(), pg_GSS_write(), pqsecure_open_gss(), and pqsecure_write().

◆ pqsecure_read()

ssize_t pqsecure_read ( PGconn conn,
void *  ptr,
size_t  len 
)

Definition at line 182 of file fe-secure.c.

183 {
184  ssize_t n;
185 
186 #ifdef USE_SSL
187  if (conn->ssl_in_use)
188  {
189  n = pgtls_read(conn, ptr, len);
190  }
191  else
192 #endif
193 #ifdef ENABLE_GSS
194  if (conn->gssenc)
195  {
196  n = pg_GSS_read(conn, ptr, len);
197  }
198  else
199 #endif
200  {
201  n = pqsecure_raw_read(conn, ptr, len);
202  }
203 
204  return n;
205 }
ssize_t pg_GSS_read(PGconn *conn, void *ptr, size_t len)
ssize_t pgtls_read(PGconn *conn, void *ptr, size_t len)
ssize_t pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
Definition: fe-secure.c:208
bool ssl_in_use
Definition: libpq-int.h:547

References conn, len, pg_GSS_read(), pgtls_read(), pqsecure_raw_read(), and pg_conn::ssl_in_use.

Referenced by pqReadData().

◆ pqsecure_write()

ssize_t pqsecure_write ( PGconn conn,
const void *  ptr,
size_t  len 
)

Definition at line 275 of file fe-secure.c.

276 {
277  ssize_t n;
278 
279 #ifdef USE_SSL
280  if (conn->ssl_in_use)
281  {
282  n = pgtls_write(conn, ptr, len);
283  }
284  else
285 #endif
286 #ifdef ENABLE_GSS
287  if (conn->gssenc)
288  {
289  n = pg_GSS_write(conn, ptr, len);
290  }
291  else
292 #endif
293  {
294  n = pqsecure_raw_write(conn, ptr, len);
295  }
296 
297  return n;
298 }
ssize_t pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len)
ssize_t pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
Definition: fe-secure.c:324

References conn, len, pg_GSS_write(), pgtls_write(), pqsecure_raw_write(), and pg_conn::ssl_in_use.

Referenced by pqSendSome().

◆ PQsetSSLKeyPassHook_OpenSSL()

void PQsetSSLKeyPassHook_OpenSSL ( PQsslKeyPassHook_OpenSSL_type  hook)

Definition at line 475 of file fe-secure.c.

476 {
477  return;
478 }

◆ PQsslAttribute()

const char* PQsslAttribute ( PGconn conn,
const char *  attribute_name 
)

Definition at line 448 of file fe-secure.c.

449 {
450  return NULL;
451 }

◆ PQsslAttributeNames()

const char* const* PQsslAttributeNames ( PGconn conn)

Definition at line 454 of file fe-secure.c.

455 {
456  static const char *const result[] = {NULL};
457 
458  return result;
459 }

◆ PQsslInUse()

int PQsslInUse ( PGconn conn)

Definition at line 103 of file fe-secure.c.

104 {
105  if (!conn)
106  return 0;
107  return conn->ssl_in_use;
108 }

References conn, and pg_conn::ssl_in_use.

Referenced by printSSLInfo().

◆ PQsslStruct()

void* PQsslStruct ( PGconn conn,
const char *  struct_name 
)

Definition at line 442 of file fe-secure.c.

443 {
444  return NULL;
445 }