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

Generated by: LCOV version 1.14