LCOV - code coverage report
Current view: top level - src/interfaces/libpq - fe-secure.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 67 119 56.3 %
Date: 2024-04-20 00:11:33 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-2024, 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             : #include <netinet/tcp.h>
      33             : #include <arpa/inet.h>
      34             : #endif
      35             : 
      36             : #include <sys/stat.h>
      37             : 
      38             : #ifdef WIN32
      39             : #include "pthread-win32.h"
      40             : #else
      41             : #include <pthread.h>
      42             : #endif
      43             : 
      44             : #include "fe-auth.h"
      45             : #include "libpq-fe.h"
      46             : #include "libpq-int.h"
      47             : 
      48             : /*
      49             :  * Macros to handle disabling and then restoring the state of SIGPIPE handling.
      50             :  * On Windows, these are all no-ops since there's no SIGPIPEs.
      51             :  */
      52             : 
      53             : #ifndef WIN32
      54             : 
      55             : #define SIGPIPE_MASKED(conn)    ((conn)->sigpipe_so || (conn)->sigpipe_flag)
      56             : 
      57             : struct sigpipe_info
      58             : {
      59             :     sigset_t    oldsigmask;
      60             :     bool        sigpipe_pending;
      61             :     bool        got_epipe;
      62             : };
      63             : 
      64             : #define DECLARE_SIGPIPE_INFO(spinfo) struct sigpipe_info spinfo
      65             : 
      66             : #define DISABLE_SIGPIPE(conn, spinfo, failaction) \
      67             :     do { \
      68             :         (spinfo).got_epipe = false; \
      69             :         if (!SIGPIPE_MASKED(conn)) \
      70             :         { \
      71             :             if (pq_block_sigpipe(&(spinfo).oldsigmask, \
      72             :                                  &(spinfo).sigpipe_pending) < 0) \
      73             :                 failaction; \
      74             :         } \
      75             :     } while (0)
      76             : 
      77             : #define REMEMBER_EPIPE(spinfo, cond) \
      78             :     do { \
      79             :         if (cond) \
      80             :             (spinfo).got_epipe = true; \
      81             :     } while (0)
      82             : 
      83             : #define RESTORE_SIGPIPE(conn, spinfo) \
      84             :     do { \
      85             :         if (!SIGPIPE_MASKED(conn)) \
      86             :             pq_reset_sigpipe(&(spinfo).oldsigmask, (spinfo).sigpipe_pending, \
      87             :                              (spinfo).got_epipe); \
      88             :     } while (0)
      89             : #else                           /* WIN32 */
      90             : 
      91             : #define DECLARE_SIGPIPE_INFO(spinfo)
      92             : #define DISABLE_SIGPIPE(conn, spinfo, failaction)
      93             : #define REMEMBER_EPIPE(spinfo, cond)
      94             : #define RESTORE_SIGPIPE(conn, spinfo)
      95             : #endif                          /* WIN32 */
      96             : 
      97             : /* ------------------------------------------------------------ */
      98             : /*           Procedures common to all secure sessions           */
      99             : /* ------------------------------------------------------------ */
     100             : 
     101             : 
     102             : int
     103           4 : PQsslInUse(PGconn *conn)
     104             : {
     105           4 :     if (!conn)
     106           0 :         return 0;
     107           4 :     return conn->ssl_in_use;
     108             : }
     109             : 
     110             : /*
     111             :  *  Exported function to allow application to tell us it's already
     112             :  *  initialized OpenSSL.
     113             :  */
     114             : void
     115           0 : PQinitSSL(int do_init)
     116             : {
     117             : #ifdef USE_SSL
     118           0 :     pgtls_init_library(do_init, do_init);
     119             : #endif
     120           0 : }
     121             : 
     122             : /*
     123             :  *  Exported function to allow application to tell us it's already
     124             :  *  initialized OpenSSL and/or libcrypto.
     125             :  */
     126             : void
     127           0 : PQinitOpenSSL(int do_ssl, int do_crypto)
     128             : {
     129             : #ifdef USE_SSL
     130           0 :     pgtls_init_library(do_ssl, do_crypto);
     131             : #endif
     132           0 : }
     133             : 
     134             : /*
     135             :  *  Initialize global SSL context
     136             :  */
     137             : int
     138       23006 : pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto)
     139             : {
     140       23006 :     int         r = 0;
     141             : 
     142             : #ifdef USE_SSL
     143       23006 :     r = pgtls_init(conn, do_ssl, do_crypto);
     144             : #endif
     145             : 
     146       23006 :     return r;
     147             : }
     148             : 
     149             : /*
     150             :  *  Begin or continue negotiating a secure session.
     151             :  */
     152             : PostgresPollingStatusType
     153         680 : pqsecure_open_client(PGconn *conn)
     154             : {
     155             : #ifdef USE_SSL
     156         680 :     return pgtls_open_client(conn);
     157             : #else
     158             :     /* shouldn't get here */
     159             :     return PGRES_POLLING_FAILED;
     160             : #endif
     161             : }
     162             : 
     163             : /*
     164             :  *  Close secure session.
     165             :  */
     166             : void
     167       45198 : pqsecure_close(PGconn *conn)
     168             : {
     169             : #ifdef USE_SSL
     170       45198 :     pgtls_close(conn);
     171             : #endif
     172       45198 : }
     173             : 
     174             : /*
     175             :  *  Read data from a secure connection.
     176             :  *
     177             :  * On failure, this function is responsible for appending a suitable message
     178             :  * to conn->errorMessage.  The caller must still inspect errno, but only
     179             :  * to determine whether to continue/retry after error.
     180             :  */
     181             : ssize_t
     182     1662678 : pqsecure_read(PGconn *conn, void *ptr, size_t len)
     183             : {
     184             :     ssize_t     n;
     185             : 
     186             : #ifdef USE_SSL
     187     1662678 :     if (conn->ssl_in_use)
     188             :     {
     189         792 :         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     1661886 :         n = pqsecure_raw_read(conn, ptr, len);
     202             :     }
     203             : 
     204     1662678 :     return n;
     205             : }
     206             : 
     207             : ssize_t
     208     1667648 : pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
     209             : {
     210             :     ssize_t     n;
     211     1667648 :     int         result_errno = 0;
     212             :     char        sebuf[PG_STRERROR_R_BUFLEN];
     213             : 
     214     1667648 :     SOCK_ERRNO_SET(0);
     215             : 
     216     1667648 :     n = recv(conn->sock, ptr, len, 0);
     217             : 
     218     1667648 :     if (n < 0)
     219             :     {
     220      554076 :         result_errno = SOCK_ERRNO;
     221             : 
     222             :         /* Set error message if appropriate */
     223      554076 :         switch (result_errno)
     224             :         {
     225             : #ifdef EAGAIN
     226      554074 :             case EAGAIN:
     227             : #endif
     228             : #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
     229             :             case EWOULDBLOCK:
     230             : #endif
     231             :             case EINTR:
     232             :                 /* no error message, caller is expected to retry */
     233      554074 :                 break;
     234             : 
     235           2 :             case EPIPE:
     236             :             case ECONNRESET:
     237           2 :                 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
     238             :                                         "\tThis probably means the server terminated abnormally\n"
     239             :                                         "\tbefore or while processing the request.");
     240           2 :                 break;
     241             : 
     242           0 :             case 0:
     243             :                 /* If errno didn't get set, treat it as regular EOF */
     244           0 :                 n = 0;
     245           0 :                 break;
     246             : 
     247           0 :             default:
     248           0 :                 libpq_append_conn_error(conn, "could not receive data from server: %s",
     249             :                                         SOCK_STRERROR(result_errno,
     250             :                                                       sebuf, sizeof(sebuf)));
     251           0 :                 break;
     252             :         }
     253     1113572 :     }
     254             : 
     255             :     /* ensure we return the intended errno to caller */
     256     1667648 :     SOCK_ERRNO_SET(result_errno);
     257             : 
     258     1667648 :     return n;
     259             : }
     260             : 
     261             : /*
     262             :  *  Write data to a secure connection.
     263             :  *
     264             :  * Returns the number of bytes written, or a negative value (with errno
     265             :  * set) upon failure.  The write count could be less than requested.
     266             :  *
     267             :  * Note that socket-level hard failures are masked from the caller,
     268             :  * instead setting conn->write_failed and storing an error message
     269             :  * in conn->write_err_msg; see pqsecure_raw_write.  This allows us to
     270             :  * postpone reporting of write failures until we're sure no error
     271             :  * message is available from the server.
     272             :  *
     273             :  * However, errors detected in the SSL or GSS management level are reported
     274             :  * via a negative result, with message appended to conn->errorMessage.
     275             :  * It's frequently unclear whether such errors should be considered read or
     276             :  * write errors, so we don't attempt to postpone reporting them.
     277             :  *
     278             :  * The caller must still inspect errno upon failure, but only to determine
     279             :  * whether to continue/retry; a message has been saved someplace in any case.
     280             :  */
     281             : ssize_t
     282      770642 : pqsecure_write(PGconn *conn, const void *ptr, size_t len)
     283             : {
     284             :     ssize_t     n;
     285             : 
     286             : #ifdef USE_SSL
     287      770642 :     if (conn->ssl_in_use)
     288             :     {
     289         512 :         n = pgtls_write(conn, ptr, len);
     290             :     }
     291             :     else
     292             : #endif
     293             : #ifdef ENABLE_GSS
     294             :     if (conn->gssenc)
     295             :     {
     296             :         n = pg_GSS_write(conn, ptr, len);
     297             :     }
     298             :     else
     299             : #endif
     300             :     {
     301      770130 :         n = pqsecure_raw_write(conn, ptr, len);
     302             :     }
     303             : 
     304      770642 :     return n;
     305             : }
     306             : 
     307             : /*
     308             :  * Low-level implementation of pqsecure_write.
     309             :  *
     310             :  * This is used directly for an unencrypted connection.  For encrypted
     311             :  * connections, this does the physical I/O on behalf of pgtls_write or
     312             :  * pg_GSS_write.
     313             :  *
     314             :  * This function reports failure (i.e., returns a negative result) only
     315             :  * for retryable errors such as EINTR.  Looping for such cases is to be
     316             :  * handled at some outer level, maybe all the way up to the application.
     317             :  * For hard failures, we set conn->write_failed and store an error message
     318             :  * in conn->write_err_msg, but then claim to have written the data anyway.
     319             :  * This is because we don't want to report write failures so long as there
     320             :  * is a possibility of reading from the server and getting an error message
     321             :  * that could explain why the connection dropped.  Many TCP stacks have
     322             :  * race conditions such that a write failure may or may not be reported
     323             :  * before all incoming data has been read.
     324             :  *
     325             :  * Note that this error behavior happens below the SSL management level when
     326             :  * we are using SSL.  That's because at least some versions of OpenSSL are
     327             :  * too quick to report a write failure when there's still a possibility to
     328             :  * get a more useful error from the server.
     329             :  */
     330             : ssize_t
     331      771504 : pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
     332             : {
     333             :     ssize_t     n;
     334      771504 :     int         flags = 0;
     335      771504 :     int         result_errno = 0;
     336             :     char        msgbuf[1024];
     337             :     char        sebuf[PG_STRERROR_R_BUFLEN];
     338             : 
     339             :     DECLARE_SIGPIPE_INFO(spinfo);
     340             : 
     341             :     /*
     342             :      * If we already had a write failure, we will never again try to send data
     343             :      * on that connection.  Even if the kernel would let us, we've probably
     344             :      * lost message boundary sync with the server.  conn->write_failed
     345             :      * therefore persists until the connection is reset, and we just discard
     346             :      * all data presented to be written.
     347             :      */
     348      771504 :     if (conn->write_failed)
     349           0 :         return len;
     350             : 
     351             : #ifdef MSG_NOSIGNAL
     352      771504 :     if (conn->sigpipe_flag)
     353      771504 :         flags |= MSG_NOSIGNAL;
     354             : 
     355      771504 : retry_masked:
     356             : #endif                          /* MSG_NOSIGNAL */
     357             : 
     358      771504 :     DISABLE_SIGPIPE(conn, spinfo, return -1);
     359             : 
     360      771504 :     n = send(conn->sock, ptr, len, flags);
     361             : 
     362      771504 :     if (n < 0)
     363             :     {
     364          68 :         result_errno = SOCK_ERRNO;
     365             : 
     366             :         /*
     367             :          * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
     368             :          * on this machine.  So, clear sigpipe_flag so we don't try the flag
     369             :          * again, and retry the send().
     370             :          */
     371             : #ifdef MSG_NOSIGNAL
     372          68 :         if (flags != 0 && result_errno == EINVAL)
     373             :         {
     374           0 :             conn->sigpipe_flag = false;
     375           0 :             flags = 0;
     376           0 :             goto retry_masked;
     377             :         }
     378             : #endif                          /* MSG_NOSIGNAL */
     379             : 
     380             :         /* Set error message if appropriate */
     381          68 :         switch (result_errno)
     382             :         {
     383             : #ifdef EAGAIN
     384          42 :             case EAGAIN:
     385             : #endif
     386             : #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
     387             :             case EWOULDBLOCK:
     388             : #endif
     389             :             case EINTR:
     390             :                 /* no error message, caller is expected to retry */
     391          42 :                 break;
     392             : 
     393          26 :             case EPIPE:
     394             :                 /* Set flag for EPIPE */
     395          26 :                 REMEMBER_EPIPE(spinfo, true);
     396             : 
     397             :                 /* FALL THRU */
     398             : 
     399             :             case ECONNRESET:
     400          26 :                 conn->write_failed = true;
     401             :                 /* Store error message in conn->write_err_msg, if possible */
     402             :                 /* (strdup failure is OK, we'll cope later) */
     403          26 :                 snprintf(msgbuf, sizeof(msgbuf),
     404          26 :                          libpq_gettext("server closed the connection unexpectedly\n"
     405             :                                        "\tThis probably means the server terminated abnormally\n"
     406             :                                        "\tbefore or while processing the request."));
     407             :                 /* keep newline out of translated string */
     408          26 :                 strlcat(msgbuf, "\n", sizeof(msgbuf));
     409          26 :                 conn->write_err_msg = strdup(msgbuf);
     410             :                 /* Now claim the write succeeded */
     411          26 :                 n = len;
     412          26 :                 break;
     413             : 
     414           0 :             default:
     415           0 :                 conn->write_failed = true;
     416             :                 /* Store error message in conn->write_err_msg, if possible */
     417             :                 /* (strdup failure is OK, we'll cope later) */
     418           0 :                 snprintf(msgbuf, sizeof(msgbuf),
     419           0 :                          libpq_gettext("could not send data to server: %s"),
     420             :                          SOCK_STRERROR(result_errno,
     421             :                                        sebuf, sizeof(sebuf)));
     422             :                 /* keep newline out of translated string */
     423           0 :                 strlcat(msgbuf, "\n", sizeof(msgbuf));
     424           0 :                 conn->write_err_msg = strdup(msgbuf);
     425             :                 /* Now claim the write succeeded */
     426           0 :                 n = len;
     427           0 :                 break;
     428             :         }
     429      771436 :     }
     430             : 
     431      771504 :     RESTORE_SIGPIPE(conn, spinfo);
     432             : 
     433             :     /* ensure we return the intended errno to caller */
     434      771504 :     SOCK_ERRNO_SET(result_errno);
     435             : 
     436      771504 :     return n;
     437             : }
     438             : 
     439             : /* Dummy versions of SSL info functions, when built without SSL support */
     440             : #ifndef USE_SSL
     441             : 
     442             : void *
     443             : PQgetssl(PGconn *conn)
     444             : {
     445             :     return NULL;
     446             : }
     447             : 
     448             : void *
     449             : PQsslStruct(PGconn *conn, const char *struct_name)
     450             : {
     451             :     return NULL;
     452             : }
     453             : 
     454             : const char *
     455             : PQsslAttribute(PGconn *conn, const char *attribute_name)
     456             : {
     457             :     return NULL;
     458             : }
     459             : 
     460             : const char *const *
     461             : PQsslAttributeNames(PGconn *conn)
     462             : {
     463             :     static const char *const result[] = {NULL};
     464             : 
     465             :     return result;
     466             : }
     467             : #endif                          /* USE_SSL */
     468             : 
     469             : /*
     470             :  * Dummy versions of OpenSSL key password hook functions, when built without
     471             :  * OpenSSL.
     472             :  */
     473             : #ifndef USE_OPENSSL
     474             : 
     475             : PQsslKeyPassHook_OpenSSL_type
     476             : PQgetSSLKeyPassHook_OpenSSL(void)
     477             : {
     478             :     return NULL;
     479             : }
     480             : 
     481             : void
     482             : PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook)
     483             : {
     484             :     return;
     485             : }
     486             : 
     487             : int
     488             : PQdefaultSSLKeyPassHook_OpenSSL(char *buf, int size, PGconn *conn)
     489             : {
     490             :     return 0;
     491             : }
     492             : #endif                          /* USE_OPENSSL */
     493             : 
     494             : /* Dummy version of GSSAPI information functions, when built without GSS support */
     495             : #ifndef ENABLE_GSS
     496             : 
     497             : void *
     498           0 : PQgetgssctx(PGconn *conn)
     499             : {
     500           0 :     return NULL;
     501             : }
     502             : 
     503             : int
     504           4 : PQgssEncInUse(PGconn *conn)
     505             : {
     506           4 :     return 0;
     507             : }
     508             : 
     509             : #endif                          /* ENABLE_GSS */
     510             : 
     511             : 
     512             : #if !defined(WIN32)
     513             : 
     514             : /*
     515             :  *  Block SIGPIPE for this thread.  This prevents send()/write() from exiting
     516             :  *  the application.
     517             :  */
     518             : int
     519           0 : pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
     520             : {
     521             :     sigset_t    sigpipe_sigset;
     522             :     sigset_t    sigset;
     523             : 
     524           0 :     sigemptyset(&sigpipe_sigset);
     525           0 :     sigaddset(&sigpipe_sigset, SIGPIPE);
     526             : 
     527             :     /* Block SIGPIPE and save previous mask for later reset */
     528           0 :     SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
     529           0 :     if (SOCK_ERRNO)
     530           0 :         return -1;
     531             : 
     532             :     /* We can have a pending SIGPIPE only if it was blocked before */
     533           0 :     if (sigismember(osigset, SIGPIPE))
     534             :     {
     535             :         /* Is there a pending SIGPIPE? */
     536           0 :         if (sigpending(&sigset) != 0)
     537           0 :             return -1;
     538             : 
     539           0 :         if (sigismember(&sigset, SIGPIPE))
     540           0 :             *sigpipe_pending = true;
     541             :         else
     542           0 :             *sigpipe_pending = false;
     543             :     }
     544             :     else
     545           0 :         *sigpipe_pending = false;
     546             : 
     547           0 :     return 0;
     548             : }
     549             : 
     550             : /*
     551             :  *  Discard any pending SIGPIPE and reset the signal mask.
     552             :  *
     553             :  * Note: we are effectively assuming here that the C library doesn't queue
     554             :  * up multiple SIGPIPE events.  If it did, then we'd accidentally leave
     555             :  * ours in the queue when an event was already pending and we got another.
     556             :  * As long as it doesn't queue multiple events, we're OK because the caller
     557             :  * can't tell the difference.
     558             :  *
     559             :  * The caller should say got_epipe = false if it is certain that it
     560             :  * didn't get an EPIPE error; in that case we'll skip the clear operation
     561             :  * and things are definitely OK, queuing or no.  If it got one or might have
     562             :  * gotten one, pass got_epipe = true.
     563             :  *
     564             :  * We do not want this to change errno, since if it did that could lose
     565             :  * the error code from a preceding send().  We essentially assume that if
     566             :  * we were able to do pq_block_sigpipe(), this can't fail.
     567             :  */
     568             : void
     569           0 : pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
     570             : {
     571           0 :     int         save_errno = SOCK_ERRNO;
     572             :     int         signo;
     573             :     sigset_t    sigset;
     574             : 
     575             :     /* Clear SIGPIPE only if none was pending */
     576           0 :     if (got_epipe && !sigpipe_pending)
     577             :     {
     578           0 :         if (sigpending(&sigset) == 0 &&
     579           0 :             sigismember(&sigset, SIGPIPE))
     580             :         {
     581             :             sigset_t    sigpipe_sigset;
     582             : 
     583           0 :             sigemptyset(&sigpipe_sigset);
     584           0 :             sigaddset(&sigpipe_sigset, SIGPIPE);
     585             : 
     586           0 :             sigwait(&sigpipe_sigset, &signo);
     587             :         }
     588             :     }
     589             : 
     590             :     /* Restore saved block mask */
     591           0 :     pthread_sigmask(SIG_SETMASK, osigset, NULL);
     592             : 
     593           0 :     SOCK_ERRNO_SET(save_errno);
     594           0 : }
     595             : 
     596             : #endif                          /* !WIN32 */

Generated by: LCOV version 1.14