LCOV - code coverage report
Current view: top level - src/interfaces/libpq - fe-secure.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 63 108 58.3 %
Date: 2020-05-31 23:07:13 Functions: 9 14 64.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * fe-secure.c
       4             :  *    functions related to setting up a secure connection to the backend.
       5             :  *    Secure connections are expected to provide confidentiality,
       6             :  *    message integrity and endpoint authentication.
       7             :  *
       8             :  *
       9             :  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
      10             :  * Portions Copyright (c) 1994, Regents of the University of California
      11             :  *
      12             :  *
      13             :  * IDENTIFICATION
      14             :  *    src/interfaces/libpq/fe-secure.c
      15             :  *
      16             :  * NOTES
      17             :  *
      18             :  *    We don't provide informational callbacks here (like
      19             :  *    info_cb() in be-secure.c), since there's no good mechanism to
      20             :  *    display such information to the user.
      21             :  *
      22             :  *-------------------------------------------------------------------------
      23             :  */
      24             : 
      25             : #include "postgres_fe.h"
      26             : 
      27             : #include <signal.h>
      28             : #include <fcntl.h>
      29             : #include <ctype.h>
      30             : 
      31             : #ifdef WIN32
      32             : #include "win32.h"
      33             : #else
      34             : #include <sys/socket.h>
      35             : #include <unistd.h>
      36             : #include <netdb.h>
      37             : #include <netinet/in.h>
      38             : #ifdef HAVE_NETINET_TCP_H
      39             : #include <netinet/tcp.h>
      40             : #endif
      41             : #include <arpa/inet.h>
      42             : #endif
      43             : 
      44             : #include <sys/stat.h>
      45             : 
      46             : #ifdef ENABLE_THREAD_SAFETY
      47             : #ifdef WIN32
      48             : #include "pthread-win32.h"
      49             : #else
      50             : #include <pthread.h>
      51             : #endif
      52             : #endif
      53             : 
      54             : #include "fe-auth.h"
      55             : #include "libpq-fe.h"
      56             : #include "libpq-int.h"
      57             : 
      58             : /*
      59             :  * Macros to handle disabling and then restoring the state of SIGPIPE handling.
      60             :  * On Windows, these are all no-ops since there's no SIGPIPEs.
      61             :  */
      62             : 
      63             : #ifndef WIN32
      64             : 
      65             : #define SIGPIPE_MASKED(conn)    ((conn)->sigpipe_so || (conn)->sigpipe_flag)
      66             : 
      67             : #ifdef ENABLE_THREAD_SAFETY
      68             : 
      69             : struct sigpipe_info
      70             : {
      71             :     sigset_t    oldsigmask;
      72             :     bool        sigpipe_pending;
      73             :     bool        got_epipe;
      74             : };
      75             : 
      76             : #define DECLARE_SIGPIPE_INFO(spinfo) struct sigpipe_info spinfo
      77             : 
      78             : #define DISABLE_SIGPIPE(conn, spinfo, failaction) \
      79             :     do { \
      80             :         (spinfo).got_epipe = false; \
      81             :         if (!SIGPIPE_MASKED(conn)) \
      82             :         { \
      83             :             if (pq_block_sigpipe(&(spinfo).oldsigmask, \
      84             :                                  &(spinfo).sigpipe_pending) < 0) \
      85             :                 failaction; \
      86             :         } \
      87             :     } while (0)
      88             : 
      89             : #define REMEMBER_EPIPE(spinfo, cond) \
      90             :     do { \
      91             :         if (cond) \
      92             :             (spinfo).got_epipe = true; \
      93             :     } while (0)
      94             : 
      95             : #define RESTORE_SIGPIPE(conn, spinfo) \
      96             :     do { \
      97             :         if (!SIGPIPE_MASKED(conn)) \
      98             :             pq_reset_sigpipe(&(spinfo).oldsigmask, (spinfo).sigpipe_pending, \
      99             :                              (spinfo).got_epipe); \
     100             :     } while (0)
     101             : #else                           /* !ENABLE_THREAD_SAFETY */
     102             : 
     103             : #define DECLARE_SIGPIPE_INFO(spinfo) pqsigfunc spinfo = NULL
     104             : 
     105             : #define DISABLE_SIGPIPE(conn, spinfo, failaction) \
     106             :     do { \
     107             :         if (!SIGPIPE_MASKED(conn)) \
     108             :             spinfo = pqsignal(SIGPIPE, SIG_IGN); \
     109             :     } while (0)
     110             : 
     111             : #define REMEMBER_EPIPE(spinfo, cond)
     112             : 
     113             : #define RESTORE_SIGPIPE(conn, spinfo) \
     114             :     do { \
     115             :         if (!SIGPIPE_MASKED(conn)) \
     116             :             pqsignal(SIGPIPE, spinfo); \
     117             :     } while (0)
     118             : #endif                          /* ENABLE_THREAD_SAFETY */
     119             : #else                           /* WIN32 */
     120             : 
     121             : #define DECLARE_SIGPIPE_INFO(spinfo)
     122             : #define DISABLE_SIGPIPE(conn, spinfo, failaction)
     123             : #define REMEMBER_EPIPE(spinfo, cond)
     124             : #define RESTORE_SIGPIPE(conn, spinfo)
     125             : #endif                          /* WIN32 */
     126             : 
     127             : /* ------------------------------------------------------------ */
     128             : /*           Procedures common to all secure sessions           */
     129             : /* ------------------------------------------------------------ */
     130             : 
     131             : 
     132             : int
     133           2 : PQsslInUse(PGconn *conn)
     134             : {
     135           2 :     if (!conn)
     136           0 :         return 0;
     137           2 :     return conn->ssl_in_use;
     138             : }
     139             : 
     140             : /*
     141             :  *  Exported function to allow application to tell us it's already
     142             :  *  initialized OpenSSL.
     143             :  */
     144             : void
     145           0 : PQinitSSL(int do_init)
     146             : {
     147             : #ifdef USE_SSL
     148           0 :     pgtls_init_library(do_init, do_init);
     149             : #endif
     150           0 : }
     151             : 
     152             : /*
     153             :  *  Exported function to allow application to tell us it's already
     154             :  *  initialized OpenSSL and/or libcrypto.
     155             :  */
     156             : void
     157           0 : PQinitOpenSSL(int do_ssl, int do_crypto)
     158             : {
     159             : #ifdef USE_SSL
     160           0 :     pgtls_init_library(do_ssl, do_crypto);
     161             : #endif
     162           0 : }
     163             : 
     164             : /*
     165             :  *  Initialize global SSL context
     166             :  */
     167             : int
     168         110 : pqsecure_initialize(PGconn *conn)
     169             : {
     170         110 :     int         r = 0;
     171             : 
     172             : #ifdef USE_SSL
     173         110 :     r = pgtls_init(conn);
     174             : #endif
     175             : 
     176         110 :     return r;
     177             : }
     178             : 
     179             : /*
     180             :  *  Begin or continue negotiating a secure session.
     181             :  */
     182             : PostgresPollingStatusType
     183         314 : pqsecure_open_client(PGconn *conn)
     184             : {
     185             : #ifdef USE_SSL
     186         314 :     return pgtls_open_client(conn);
     187             : #else
     188             :     /* shouldn't get here */
     189             :     return PGRES_POLLING_FAILED;
     190             : #endif
     191             : }
     192             : 
     193             : /*
     194             :  *  Close secure session.
     195             :  */
     196             : void
     197       17428 : pqsecure_close(PGconn *conn)
     198             : {
     199             : #ifdef USE_SSL
     200       17428 :     if (conn->ssl_in_use)
     201          76 :         pgtls_close(conn);
     202             : #endif
     203       17428 : }
     204             : 
     205             : /*
     206             :  *  Read data from a secure connection.
     207             :  *
     208             :  * On failure, this function is responsible for putting a suitable message
     209             :  * into conn->errorMessage.  The caller must still inspect errno, but only
     210             :  * to determine whether to continue/retry after error.
     211             :  */
     212             : ssize_t
     213      795278 : pqsecure_read(PGconn *conn, void *ptr, size_t len)
     214             : {
     215             :     ssize_t     n;
     216             : 
     217             : #ifdef USE_SSL
     218      795278 :     if (conn->ssl_in_use)
     219             :     {
     220         294 :         n = pgtls_read(conn, ptr, len);
     221             :     }
     222             :     else
     223             : #endif
     224             : #ifdef ENABLE_GSS
     225             :     if (conn->gssenc)
     226             :     {
     227             :         n = pg_GSS_read(conn, ptr, len);
     228             :     }
     229             :     else
     230             : #endif
     231             :     {
     232      794984 :         n = pqsecure_raw_read(conn, ptr, len);
     233             :     }
     234             : 
     235      795278 :     return n;
     236             : }
     237             : 
     238             : ssize_t
     239      797492 : pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
     240             : {
     241             :     ssize_t     n;
     242      797492 :     int         result_errno = 0;
     243             :     char        sebuf[PG_STRERROR_R_BUFLEN];
     244             : 
     245      797492 :     n = recv(conn->sock, ptr, len, 0);
     246             : 
     247      797492 :     if (n < 0)
     248             :     {
     249      229704 :         result_errno = SOCK_ERRNO;
     250             : 
     251             :         /* Set error message if appropriate */
     252      229704 :         switch (result_errno)
     253             :         {
     254             : #ifdef EAGAIN
     255      229692 :             case EAGAIN:
     256             : #endif
     257             : #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
     258             :             case EWOULDBLOCK:
     259             : #endif
     260             :             case EINTR:
     261             :                 /* no error message, caller is expected to retry */
     262      229692 :                 break;
     263             : 
     264             : #ifdef ECONNRESET
     265          12 :             case ECONNRESET:
     266          12 :                 printfPQExpBuffer(&conn->errorMessage,
     267          12 :                                   libpq_gettext("server closed the connection unexpectedly\n"
     268             :                                                 "\tThis probably means the server terminated abnormally\n"
     269             :                                                 "\tbefore or while processing the request.\n"));
     270          12 :                 break;
     271             : #endif
     272             : 
     273           0 :             default:
     274           0 :                 printfPQExpBuffer(&conn->errorMessage,
     275           0 :                                   libpq_gettext("could not receive data from server: %s\n"),
     276             :                                   SOCK_STRERROR(result_errno,
     277             :                                                 sebuf, sizeof(sebuf)));
     278           0 :                 break;
     279             :         }
     280      567788 :     }
     281             : 
     282             :     /* ensure we return the intended errno to caller */
     283      797492 :     SOCK_ERRNO_SET(result_errno);
     284             : 
     285      797492 :     return n;
     286             : }
     287             : 
     288             : /*
     289             :  *  Write data to a secure connection.
     290             :  *
     291             :  * On failure, this function is responsible for putting a suitable message
     292             :  * into conn->errorMessage.  The caller must still inspect errno, but only
     293             :  * to determine whether to continue/retry after error.
     294             :  */
     295             : ssize_t
     296      353296 : pqsecure_write(PGconn *conn, const void *ptr, size_t len)
     297             : {
     298             :     ssize_t     n;
     299             : 
     300             : #ifdef USE_SSL
     301      353296 :     if (conn->ssl_in_use)
     302             :     {
     303         212 :         n = pgtls_write(conn, ptr, len);
     304             :     }
     305             :     else
     306             : #endif
     307             : #ifdef ENABLE_GSS
     308             :     if (conn->gssenc)
     309             :     {
     310             :         n = pg_GSS_write(conn, ptr, len);
     311             :     }
     312             :     else
     313             : #endif
     314             :     {
     315      353084 :         n = pqsecure_raw_write(conn, ptr, len);
     316             :     }
     317             : 
     318      353296 :     return n;
     319             : }
     320             : 
     321             : ssize_t
     322      353686 : pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
     323             : {
     324             :     ssize_t     n;
     325      353686 :     int         flags = 0;
     326      353686 :     int         result_errno = 0;
     327             :     char        sebuf[PG_STRERROR_R_BUFLEN];
     328             : 
     329             :     DECLARE_SIGPIPE_INFO(spinfo);
     330             : 
     331             : #ifdef MSG_NOSIGNAL
     332      353686 :     if (conn->sigpipe_flag)
     333      353686 :         flags |= MSG_NOSIGNAL;
     334             : 
     335      353686 : retry_masked:
     336             : #endif                          /* MSG_NOSIGNAL */
     337             : 
     338      353686 :     DISABLE_SIGPIPE(conn, spinfo, return -1);
     339             : 
     340      353686 :     n = send(conn->sock, ptr, len, flags);
     341             : 
     342      353686 :     if (n < 0)
     343             :     {
     344          40 :         result_errno = SOCK_ERRNO;
     345             : 
     346             :         /*
     347             :          * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
     348             :          * on this machine.  So, clear sigpipe_flag so we don't try the flag
     349             :          * again, and retry the send().
     350             :          */
     351             : #ifdef MSG_NOSIGNAL
     352          40 :         if (flags != 0 && result_errno == EINVAL)
     353             :         {
     354           0 :             conn->sigpipe_flag = false;
     355           0 :             flags = 0;
     356           0 :             goto retry_masked;
     357             :         }
     358             : #endif                          /* MSG_NOSIGNAL */
     359             : 
     360             :         /* Set error message if appropriate */
     361          40 :         switch (result_errno)
     362             :         {
     363             : #ifdef EAGAIN
     364          36 :             case EAGAIN:
     365             : #endif
     366             : #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
     367             :             case EWOULDBLOCK:
     368             : #endif
     369             :             case EINTR:
     370             :                 /* no error message, caller is expected to retry */
     371          36 :                 break;
     372             : 
     373           4 :             case EPIPE:
     374             :                 /* Set flag for EPIPE */
     375           4 :                 REMEMBER_EPIPE(spinfo, true);
     376             : 
     377             : #ifdef ECONNRESET
     378             :                 /* FALL THRU */
     379             : 
     380             :             case ECONNRESET:
     381             : #endif
     382           4 :                 printfPQExpBuffer(&conn->errorMessage,
     383           4 :                                   libpq_gettext("server closed the connection unexpectedly\n"
     384             :                                                 "\tThis probably means the server terminated abnormally\n"
     385             :                                                 "\tbefore or while processing the request.\n"));
     386           4 :                 break;
     387             : 
     388           0 :             default:
     389           0 :                 printfPQExpBuffer(&conn->errorMessage,
     390           0 :                                   libpq_gettext("could not send data to server: %s\n"),
     391             :                                   SOCK_STRERROR(result_errno,
     392             :                                                 sebuf, sizeof(sebuf)));
     393           0 :                 break;
     394             :         }
     395      353646 :     }
     396             : 
     397      353686 :     RESTORE_SIGPIPE(conn, spinfo);
     398             : 
     399             :     /* ensure we return the intended errno to caller */
     400      353686 :     SOCK_ERRNO_SET(result_errno);
     401             : 
     402      353686 :     return n;
     403             : }
     404             : 
     405             : /* Dummy versions of SSL info functions, when built without SSL support */
     406             : #ifndef USE_SSL
     407             : 
     408             : void *
     409             : PQgetssl(PGconn *conn)
     410             : {
     411             :     return NULL;
     412             : }
     413             : 
     414             : void *
     415             : PQsslStruct(PGconn *conn, const char *struct_name)
     416             : {
     417             :     return NULL;
     418             : }
     419             : 
     420             : const char *
     421             : PQsslAttribute(PGconn *conn, const char *attribute_name)
     422             : {
     423             :     return NULL;
     424             : }
     425             : 
     426             : const char *const *
     427             : PQsslAttributeNames(PGconn *conn)
     428             : {
     429             :     static const char *const result[] = {NULL};
     430             : 
     431             :     return result;
     432             : }
     433             : 
     434             : PQsslKeyPassHook_OpenSSL_type
     435             : PQgetSSLKeyPassHook_OpenSSL(void)
     436             : {
     437             :     return NULL;
     438             : }
     439             : 
     440             : void
     441             : PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook)
     442             : {
     443             :     return;
     444             : }
     445             : 
     446             : int
     447             : PQdefaultSSLKeyPassHook_OpenSSL(char *buf, int size, PGconn *conn)
     448             : {
     449             :     return 0;
     450             : }
     451             : #endif                          /* USE_SSL */
     452             : 
     453             : /* Dummy version of GSSAPI information functions, when built without GSS support */
     454             : #ifndef ENABLE_GSS
     455             : 
     456             : void *
     457           0 : PQgetgssctx(PGconn *conn)
     458             : {
     459           0 :     return NULL;
     460             : }
     461             : 
     462             : int
     463           2 : PQgssEncInUse(PGconn *conn)
     464             : {
     465           2 :     return 0;
     466             : }
     467             : 
     468             : #endif                          /* ENABLE_GSS */
     469             : 
     470             : 
     471             : #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
     472             : 
     473             : /*
     474             :  *  Block SIGPIPE for this thread.  This prevents send()/write() from exiting
     475             :  *  the application.
     476             :  */
     477             : int
     478           0 : pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
     479             : {
     480             :     sigset_t    sigpipe_sigset;
     481             :     sigset_t    sigset;
     482             : 
     483           0 :     sigemptyset(&sigpipe_sigset);
     484           0 :     sigaddset(&sigpipe_sigset, SIGPIPE);
     485             : 
     486             :     /* Block SIGPIPE and save previous mask for later reset */
     487           0 :     SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
     488           0 :     if (SOCK_ERRNO)
     489           0 :         return -1;
     490             : 
     491             :     /* We can have a pending SIGPIPE only if it was blocked before */
     492           0 :     if (sigismember(osigset, SIGPIPE))
     493             :     {
     494             :         /* Is there a pending SIGPIPE? */
     495           0 :         if (sigpending(&sigset) != 0)
     496           0 :             return -1;
     497             : 
     498           0 :         if (sigismember(&sigset, SIGPIPE))
     499           0 :             *sigpipe_pending = true;
     500             :         else
     501           0 :             *sigpipe_pending = false;
     502             :     }
     503             :     else
     504           0 :         *sigpipe_pending = false;
     505             : 
     506           0 :     return 0;
     507             : }
     508             : 
     509             : /*
     510             :  *  Discard any pending SIGPIPE and reset the signal mask.
     511             :  *
     512             :  * Note: we are effectively assuming here that the C library doesn't queue
     513             :  * up multiple SIGPIPE events.  If it did, then we'd accidentally leave
     514             :  * ours in the queue when an event was already pending and we got another.
     515             :  * As long as it doesn't queue multiple events, we're OK because the caller
     516             :  * can't tell the difference.
     517             :  *
     518             :  * The caller should say got_epipe = false if it is certain that it
     519             :  * didn't get an EPIPE error; in that case we'll skip the clear operation
     520             :  * and things are definitely OK, queuing or no.  If it got one or might have
     521             :  * gotten one, pass got_epipe = true.
     522             :  *
     523             :  * We do not want this to change errno, since if it did that could lose
     524             :  * the error code from a preceding send().  We essentially assume that if
     525             :  * we were able to do pq_block_sigpipe(), this can't fail.
     526             :  */
     527             : void
     528           0 : pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
     529             : {
     530           0 :     int         save_errno = SOCK_ERRNO;
     531             :     int         signo;
     532             :     sigset_t    sigset;
     533             : 
     534             :     /* Clear SIGPIPE only if none was pending */
     535           0 :     if (got_epipe && !sigpipe_pending)
     536             :     {
     537           0 :         if (sigpending(&sigset) == 0 &&
     538           0 :             sigismember(&sigset, SIGPIPE))
     539             :         {
     540             :             sigset_t    sigpipe_sigset;
     541             : 
     542           0 :             sigemptyset(&sigpipe_sigset);
     543           0 :             sigaddset(&sigpipe_sigset, SIGPIPE);
     544             : 
     545           0 :             sigwait(&sigpipe_sigset, &signo);
     546             :         }
     547             :     }
     548             : 
     549             :     /* Restore saved block mask */
     550           0 :     pthread_sigmask(SIG_SETMASK, osigset, NULL);
     551             : 
     552           0 :     SOCK_ERRNO_SET(save_errno);
     553           0 : }
     554             : 
     555             : #endif                          /* ENABLE_THREAD_SAFETY && !WIN32 */

Generated by: LCOV version 1.13