LCOV - code coverage report
Current view: top level - src/interfaces/libpq - fe-secure.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 51 99 51.5 %
Date: 2019-11-13 22:07:24 Functions: 7 14 50.0 %
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-2019, 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           0 : PQsslInUse(PGconn *conn)
     134             : {
     135           0 :     if (!conn)
     136           0 :         return 0;
     137           0 :     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         100 : pqsecure_initialize(PGconn *conn)
     169             : {
     170         100 :     int         r = 0;
     171             : 
     172             : #ifdef USE_SSL
     173         100 :     r = pgtls_init(conn);
     174             : #endif
     175             : 
     176         100 :     return r;
     177             : }
     178             : 
     179             : /*
     180             :  *  Begin or continue negotiating a secure session.
     181             :  */
     182             : PostgresPollingStatusType
     183         276 : pqsecure_open_client(PGconn *conn)
     184             : {
     185             : #ifdef USE_SSL
     186         276 :     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       15090 : pqsecure_close(PGconn *conn)
     198             : {
     199             : #ifdef USE_SSL
     200       15090 :     if (conn->ssl_in_use)
     201          64 :         pgtls_close(conn);
     202             : #endif
     203       15090 : }
     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      641142 : pqsecure_read(PGconn *conn, void *ptr, size_t len)
     214             : {
     215             :     ssize_t     n;
     216             : 
     217             : #ifdef USE_SSL
     218      641142 :     if (conn->ssl_in_use)
     219             :     {
     220         184 :         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      640958 :         n = pqsecure_raw_read(conn, ptr, len);
     233             :     }
     234             : 
     235      641148 :     return n;
     236             : }
     237             : 
     238             : ssize_t
     239      642636 : pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
     240             : {
     241             :     ssize_t     n;
     242      642636 :     int         result_errno = 0;
     243             :     char        sebuf[PG_STRERROR_R_BUFLEN];
     244             : 
     245      642636 :     n = recv(conn->sock, ptr, len, 0);
     246             : 
     247      642636 :     if (n < 0)
     248             :     {
     249      195440 :         result_errno = SOCK_ERRNO;
     250             : 
     251             :         /* Set error message if appropriate */
     252      195438 :         switch (result_errno)
     253             :         {
     254             : #ifdef EAGAIN
     255             :             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      195432 :                 break;
     263             : 
     264             : #ifdef ECONNRESET
     265             :             case ECONNRESET:
     266           6 :                 printfPQExpBuffer(&conn->errorMessage,
     267           6 :                                   libpq_gettext(
     268             :                                                 "server closed the connection unexpectedly\n"
     269             :                                                 "\tThis probably means the server terminated abnormally\n"
     270             :                                                 "\tbefore or while processing the request.\n"));
     271           6 :                 break;
     272             : #endif
     273             : 
     274             :             default:
     275           0 :                 printfPQExpBuffer(&conn->errorMessage,
     276           0 :                                   libpq_gettext("could not receive data from server: %s\n"),
     277             :                                   SOCK_STRERROR(result_errno,
     278             :                                                 sebuf, sizeof(sebuf)));
     279           0 :                 break;
     280             :         }
     281             :     }
     282             : 
     283             :     /* ensure we return the intended errno to caller */
     284      642634 :     SOCK_ERRNO_SET(result_errno);
     285             : 
     286      642636 :     return n;
     287             : }
     288             : 
     289             : /*
     290             :  *  Write data to a secure connection.
     291             :  *
     292             :  * On failure, this function is responsible for putting a suitable message
     293             :  * into conn->errorMessage.  The caller must still inspect errno, but only
     294             :  * to determine whether to continue/retry after error.
     295             :  */
     296             : ssize_t
     297      328146 : pqsecure_write(PGconn *conn, const void *ptr, size_t len)
     298             : {
     299             :     ssize_t     n;
     300             : 
     301             : #ifdef USE_SSL
     302      328146 :     if (conn->ssl_in_use)
     303             :     {
     304         184 :         n = pgtls_write(conn, ptr, len);
     305             :     }
     306             :     else
     307             : #endif
     308             : #ifdef ENABLE_GSS
     309             :     if (conn->gssenc)
     310             :     {
     311             :         n = pg_GSS_write(conn, ptr, len);
     312             :     }
     313             :     else
     314             : #endif
     315             :     {
     316      327962 :         n = pqsecure_raw_write(conn, ptr, len);
     317             :     }
     318             : 
     319      328154 :     return n;
     320             : }
     321             : 
     322             : ssize_t
     323      328412 : pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
     324             : {
     325             :     ssize_t     n;
     326      328412 :     int         flags = 0;
     327      328412 :     int         result_errno = 0;
     328             :     char        sebuf[PG_STRERROR_R_BUFLEN];
     329             : 
     330             :     DECLARE_SIGPIPE_INFO(spinfo);
     331             : 
     332             : #ifdef MSG_NOSIGNAL
     333      328412 :     if (conn->sigpipe_flag)
     334      328414 :         flags |= MSG_NOSIGNAL;
     335             : 
     336             : retry_masked:
     337             : #endif                          /* MSG_NOSIGNAL */
     338             : 
     339      328412 :     DISABLE_SIGPIPE(conn, spinfo, return -1);
     340             : 
     341      328410 :     n = send(conn->sock, ptr, len, flags);
     342             : 
     343      328420 :     if (n < 0)
     344             :     {
     345          40 :         result_errno = SOCK_ERRNO;
     346             : 
     347             :         /*
     348             :          * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
     349             :          * on this machine.  So, clear sigpipe_flag so we don't try the flag
     350             :          * again, and retry the send().
     351             :          */
     352             : #ifdef MSG_NOSIGNAL
     353          40 :         if (flags != 0 && result_errno == EINVAL)
     354             :         {
     355           0 :             conn->sigpipe_flag = false;
     356           0 :             flags = 0;
     357           0 :             goto retry_masked;
     358             :         }
     359             : #endif                          /* MSG_NOSIGNAL */
     360             : 
     361             :         /* Set error message if appropriate */
     362          40 :         switch (result_errno)
     363             :         {
     364             : #ifdef EAGAIN
     365             :             case EAGAIN:
     366             : #endif
     367             : #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
     368             :             case EWOULDBLOCK:
     369             : #endif
     370             :             case EINTR:
     371             :                 /* no error message, caller is expected to retry */
     372          36 :                 break;
     373             : 
     374             :             case EPIPE:
     375             :                 /* Set flag for EPIPE */
     376           4 :                 REMEMBER_EPIPE(spinfo, true);
     377             : 
     378             : #ifdef ECONNRESET
     379             :                 /* FALL THRU */
     380             : 
     381             :             case ECONNRESET:
     382             : #endif
     383           4 :                 printfPQExpBuffer(&conn->errorMessage,
     384           4 :                                   libpq_gettext(
     385             :                                                 "server closed the connection unexpectedly\n"
     386             :                                                 "\tThis probably means the server terminated abnormally\n"
     387             :                                                 "\tbefore or while processing the request.\n"));
     388           4 :                 break;
     389             : 
     390             :             default:
     391           0 :                 printfPQExpBuffer(&conn->errorMessage,
     392           0 :                                   libpq_gettext("could not send data to server: %s\n"),
     393             :                                   SOCK_STRERROR(result_errno,
     394             :                                                 sebuf, sizeof(sebuf)));
     395           0 :                 break;
     396             :         }
     397             :     }
     398             : 
     399      328420 :     RESTORE_SIGPIPE(conn, spinfo);
     400             : 
     401             :     /* ensure we return the intended errno to caller */
     402      328420 :     SOCK_ERRNO_SET(result_errno);
     403             : 
     404      328416 :     return n;
     405             : }
     406             : 
     407             : /* Dummy versions of SSL info functions, when built without SSL support */
     408             : #ifndef USE_SSL
     409             : 
     410             : void *
     411             : PQgetssl(PGconn *conn)
     412             : {
     413             :     return NULL;
     414             : }
     415             : 
     416             : void *
     417             : PQsslStruct(PGconn *conn, const char *struct_name)
     418             : {
     419             :     return NULL;
     420             : }
     421             : 
     422             : const char *
     423             : PQsslAttribute(PGconn *conn, const char *attribute_name)
     424             : {
     425             :     return NULL;
     426             : }
     427             : 
     428             : const char *const *
     429             : PQsslAttributeNames(PGconn *conn)
     430             : {
     431             :     static const char *const result[] = {NULL};
     432             : 
     433             :     return result;
     434             : }
     435             : #endif                          /* USE_SSL */
     436             : 
     437             : /* Dummy version of GSSAPI information functions, when built without GSS support */
     438             : #ifndef ENABLE_GSS
     439             : 
     440             : void *
     441           0 : PQgetgssctx(PGconn *conn)
     442             : {
     443           0 :     return NULL;
     444             : }
     445             : 
     446             : int
     447           0 : PQgssEncInUse(PGconn *conn)
     448             : {
     449           0 :     return 0;
     450             : }
     451             : 
     452             : #endif                          /* ENABLE_GSS */
     453             : 
     454             : 
     455             : #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
     456             : 
     457             : /*
     458             :  *  Block SIGPIPE for this thread.  This prevents send()/write() from exiting
     459             :  *  the application.
     460             :  */
     461             : int
     462           0 : pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
     463             : {
     464             :     sigset_t    sigpipe_sigset;
     465             :     sigset_t    sigset;
     466             : 
     467           0 :     sigemptyset(&sigpipe_sigset);
     468           0 :     sigaddset(&sigpipe_sigset, SIGPIPE);
     469             : 
     470             :     /* Block SIGPIPE and save previous mask for later reset */
     471           0 :     SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
     472           0 :     if (SOCK_ERRNO)
     473           0 :         return -1;
     474             : 
     475             :     /* We can have a pending SIGPIPE only if it was blocked before */
     476           0 :     if (sigismember(osigset, SIGPIPE))
     477             :     {
     478             :         /* Is there a pending SIGPIPE? */
     479           0 :         if (sigpending(&sigset) != 0)
     480           0 :             return -1;
     481             : 
     482           0 :         if (sigismember(&sigset, SIGPIPE))
     483           0 :             *sigpipe_pending = true;
     484             :         else
     485           0 :             *sigpipe_pending = false;
     486             :     }
     487             :     else
     488           0 :         *sigpipe_pending = false;
     489             : 
     490           0 :     return 0;
     491             : }
     492             : 
     493             : /*
     494             :  *  Discard any pending SIGPIPE and reset the signal mask.
     495             :  *
     496             :  * Note: we are effectively assuming here that the C library doesn't queue
     497             :  * up multiple SIGPIPE events.  If it did, then we'd accidentally leave
     498             :  * ours in the queue when an event was already pending and we got another.
     499             :  * As long as it doesn't queue multiple events, we're OK because the caller
     500             :  * can't tell the difference.
     501             :  *
     502             :  * The caller should say got_epipe = false if it is certain that it
     503             :  * didn't get an EPIPE error; in that case we'll skip the clear operation
     504             :  * and things are definitely OK, queuing or no.  If it got one or might have
     505             :  * gotten one, pass got_epipe = true.
     506             :  *
     507             :  * We do not want this to change errno, since if it did that could lose
     508             :  * the error code from a preceding send().  We essentially assume that if
     509             :  * we were able to do pq_block_sigpipe(), this can't fail.
     510             :  */
     511             : void
     512           0 : pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
     513             : {
     514           0 :     int         save_errno = SOCK_ERRNO;
     515             :     int         signo;
     516             :     sigset_t    sigset;
     517             : 
     518             :     /* Clear SIGPIPE only if none was pending */
     519           0 :     if (got_epipe && !sigpipe_pending)
     520             :     {
     521           0 :         if (sigpending(&sigset) == 0 &&
     522           0 :             sigismember(&sigset, SIGPIPE))
     523             :         {
     524             :             sigset_t    sigpipe_sigset;
     525             : 
     526           0 :             sigemptyset(&sigpipe_sigset);
     527           0 :             sigaddset(&sigpipe_sigset, SIGPIPE);
     528             : 
     529           0 :             sigwait(&sigpipe_sigset, &signo);
     530             :         }
     531             :     }
     532             : 
     533             :     /* Restore saved block mask */
     534           0 :     pthread_sigmask(SIG_SETMASK, osigset, NULL);
     535             : 
     536           0 :     SOCK_ERRNO_SET(save_errno);
     537           0 : }
     538             : 
     539             : #endif                          /* ENABLE_THREAD_SAFETY && !WIN32 */

Generated by: LCOV version 1.13