LCOV - code coverage report
Current view: top level - src/backend/libpq - be-secure.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17beta1 Lines: 63 83 75.9 %
Date: 2024-06-17 22:11:45 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * be-secure.c
       4             :  *    functions related to setting up a secure connection to the frontend.
       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/backend/libpq/be-secure.c
      15             :  *
      16             :  *-------------------------------------------------------------------------
      17             :  */
      18             : 
      19             : #include "postgres.h"
      20             : 
      21             : #include <signal.h>
      22             : #include <fcntl.h>
      23             : #include <ctype.h>
      24             : #include <sys/socket.h>
      25             : #include <netdb.h>
      26             : #include <netinet/in.h>
      27             : #include <netinet/tcp.h>
      28             : #include <arpa/inet.h>
      29             : 
      30             : #include "libpq/libpq.h"
      31             : #include "miscadmin.h"
      32             : #include "tcop/tcopprot.h"
      33             : #include "utils/wait_event.h"
      34             : 
      35             : char       *ssl_library;
      36             : char       *ssl_cert_file;
      37             : char       *ssl_key_file;
      38             : char       *ssl_ca_file;
      39             : char       *ssl_crl_file;
      40             : char       *ssl_crl_dir;
      41             : char       *ssl_dh_params_file;
      42             : char       *ssl_passphrase_command;
      43             : bool        ssl_passphrase_command_supports_reload;
      44             : 
      45             : #ifdef USE_SSL
      46             : bool        ssl_loaded_verify_locations = false;
      47             : #endif
      48             : 
      49             : /* GUC variable controlling SSL cipher list */
      50             : char       *SSLCipherSuites = NULL;
      51             : 
      52             : /* GUC variable for default ECHD curve. */
      53             : char       *SSLECDHCurve;
      54             : 
      55             : /* GUC variable: if false, prefer client ciphers */
      56             : bool        SSLPreferServerCiphers;
      57             : 
      58             : int         ssl_min_protocol_version = PG_TLS1_2_VERSION;
      59             : int         ssl_max_protocol_version = PG_TLS_ANY;
      60             : 
      61             : /* ------------------------------------------------------------ */
      62             : /*           Procedures common to all secure sessions           */
      63             : /* ------------------------------------------------------------ */
      64             : 
      65             : /*
      66             :  *  Initialize global context.
      67             :  *
      68             :  * If isServerStart is true, report any errors as FATAL (so we don't return).
      69             :  * Otherwise, log errors at LOG level and return -1 to indicate trouble,
      70             :  * preserving the old SSL state if any.  Returns 0 if OK.
      71             :  */
      72             : int
      73          52 : secure_initialize(bool isServerStart)
      74             : {
      75             : #ifdef USE_SSL
      76          52 :     return be_tls_init(isServerStart);
      77             : #else
      78             :     return 0;
      79             : #endif
      80             : }
      81             : 
      82             : /*
      83             :  *  Destroy global context, if any.
      84             :  */
      85             : void
      86         246 : secure_destroy(void)
      87             : {
      88             : #ifdef USE_SSL
      89         246 :     be_tls_destroy();
      90             : #endif
      91         246 : }
      92             : 
      93             : /*
      94             :  * Indicate if we have loaded the root CA store to verify certificates
      95             :  */
      96             : bool
      97          60 : secure_loaded_verify_locations(void)
      98             : {
      99             : #ifdef USE_SSL
     100          60 :     return ssl_loaded_verify_locations;
     101             : #else
     102             :     return false;
     103             : #endif
     104             : }
     105             : 
     106             : /*
     107             :  *  Attempt to negotiate secure session.
     108             :  */
     109             : int
     110         226 : secure_open_server(Port *port)
     111             : {
     112             : #ifdef USE_SSL
     113         226 :     int         r = 0;
     114             :     ssize_t     len;
     115             : 
     116             :     /* push unencrypted buffered data back through SSL setup */
     117         226 :     len = pq_buffer_remaining_data();
     118         226 :     if (len > 0)
     119             :     {
     120           0 :         char       *buf = palloc(len);
     121             : 
     122           0 :         pq_startmsgread();
     123           0 :         if (pq_getbytes(buf, len) == EOF)
     124           0 :             return STATUS_ERROR;    /* shouldn't be possible */
     125           0 :         pq_endmsgread();
     126           0 :         port->raw_buf = buf;
     127           0 :         port->raw_buf_remaining = len;
     128           0 :         port->raw_buf_consumed = 0;
     129             :     }
     130             :     Assert(pq_buffer_remaining_data() == 0);
     131             : 
     132         226 :     r = be_tls_open_server(port);
     133             : 
     134         226 :     if (port->raw_buf_remaining > 0)
     135             :     {
     136             :         /*
     137             :          * This shouldn't be possible -- it would mean the client sent
     138             :          * encrypted data before we established a session key...
     139             :          */
     140           0 :         elog(LOG, "buffered unencrypted data remains after negotiating SSL connection");
     141           0 :         return STATUS_ERROR;
     142             :     }
     143         226 :     if (port->raw_buf != NULL)
     144             :     {
     145           0 :         pfree(port->raw_buf);
     146           0 :         port->raw_buf = NULL;
     147             :     }
     148             : 
     149         226 :     ereport(DEBUG2,
     150             :             (errmsg_internal("SSL connection from DN:\"%s\" CN:\"%s\"",
     151             :                              port->peer_dn ? port->peer_dn : "(anonymous)",
     152             :                              port->peer_cn ? port->peer_cn : "(anonymous)")));
     153         226 :     return r;
     154             : #else
     155             :     return 0;
     156             : #endif
     157             : }
     158             : 
     159             : /*
     160             :  *  Close secure session.
     161             :  */
     162             : void
     163       21050 : secure_close(Port *port)
     164             : {
     165             : #ifdef USE_SSL
     166       21050 :     if (port->ssl_in_use)
     167         226 :         be_tls_close(port);
     168             : #endif
     169       21050 : }
     170             : 
     171             : /*
     172             :  *  Read data from a secure connection.
     173             :  */
     174             : ssize_t
     175     2614778 : secure_read(Port *port, void *ptr, size_t len)
     176             : {
     177             :     ssize_t     n;
     178             :     int         waitfor;
     179             : 
     180             :     /* Deal with any already-pending interrupt condition. */
     181     2614778 :     ProcessClientReadInterrupt(false);
     182             : 
     183     2842692 : retry:
     184             : #ifdef USE_SSL
     185     2842692 :     waitfor = 0;
     186     2842692 :     if (port->ssl_in_use)
     187             :     {
     188         866 :         n = be_tls_read(port, ptr, len, &waitfor);
     189             :     }
     190             :     else
     191             : #endif
     192             : #ifdef ENABLE_GSS
     193             :     if (port->gss && port->gss->enc)
     194             :     {
     195             :         n = be_gssapi_read(port, ptr, len);
     196             :         waitfor = WL_SOCKET_READABLE;
     197             :     }
     198             :     else
     199             : #endif
     200             :     {
     201     2841826 :         n = secure_raw_read(port, ptr, len);
     202     2841826 :         waitfor = WL_SOCKET_READABLE;
     203             :     }
     204             : 
     205             :     /* In blocking mode, wait until the socket is ready */
     206     2842692 :     if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
     207             :     {
     208             :         WaitEvent   event;
     209             : 
     210             :         Assert(waitfor);
     211             : 
     212      227980 :         ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetSocketPos, waitfor, NULL);
     213             : 
     214      227980 :         WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
     215             :                          WAIT_EVENT_CLIENT_READ);
     216             : 
     217             :         /*
     218             :          * If the postmaster has died, it's not safe to continue running,
     219             :          * because it is the postmaster's job to kill us if some other backend
     220             :          * exits uncleanly.  Moreover, we won't run very well in this state;
     221             :          * helper processes like walwriter and the bgwriter will exit, so
     222             :          * performance may be poor.  Finally, if we don't exit, pg_ctl will be
     223             :          * unable to restart the postmaster without manual intervention, so no
     224             :          * new connections can be accepted.  Exiting clears the deck for a
     225             :          * postmaster restart.
     226             :          *
     227             :          * (Note that we only make this check when we would otherwise sleep on
     228             :          * our latch.  We might still continue running for a while if the
     229             :          * postmaster is killed in mid-query, or even through multiple queries
     230             :          * if we never have to wait for read.  We don't want to burn too many
     231             :          * cycles checking for this very rare condition, and this should cause
     232             :          * us to exit quickly in most cases.)
     233             :          */
     234      227980 :         if (event.events & WL_POSTMASTER_DEATH)
     235           0 :             ereport(FATAL,
     236             :                     (errcode(ERRCODE_ADMIN_SHUTDOWN),
     237             :                      errmsg("terminating connection due to unexpected postmaster exit")));
     238             : 
     239             :         /* Handle interrupt. */
     240      227980 :         if (event.events & WL_LATCH_SET)
     241             :         {
     242       18386 :             ResetLatch(MyLatch);
     243       18386 :             ProcessClientReadInterrupt(true);
     244             : 
     245             :             /*
     246             :              * We'll retry the read. Most likely it will return immediately
     247             :              * because there's still no data available, and we'll wait for the
     248             :              * socket to become ready again.
     249             :              */
     250             :         }
     251      227960 :         goto retry;
     252             :     }
     253             : 
     254             :     /*
     255             :      * Process interrupts that happened during a successful (or non-blocking,
     256             :      * or hard-failed) read.
     257             :      */
     258     2614712 :     ProcessClientReadInterrupt(false);
     259             : 
     260     2614712 :     return n;
     261             : }
     262             : 
     263             : ssize_t
     264     2845980 : secure_raw_read(Port *port, void *ptr, size_t len)
     265             : {
     266             :     ssize_t     n;
     267             : 
     268             :     /* Read from the "unread" buffered data first. c.f. libpq-be.h */
     269     2845980 :     if (port->raw_buf_remaining > 0)
     270             :     {
     271             :         /* consume up to len bytes from the raw_buf */
     272           0 :         if (len > port->raw_buf_remaining)
     273           0 :             len = port->raw_buf_remaining;
     274             :         Assert(port->raw_buf);
     275           0 :         memcpy(ptr, port->raw_buf + port->raw_buf_consumed, len);
     276           0 :         port->raw_buf_consumed += len;
     277           0 :         port->raw_buf_remaining -= len;
     278           0 :         return len;
     279             :     }
     280             : 
     281             :     /*
     282             :      * Try to read from the socket without blocking. If it succeeds we're
     283             :      * done, otherwise we'll wait for the socket using the latch mechanism.
     284             :      */
     285             : #ifdef WIN32
     286             :     pgwin32_noblock = true;
     287             : #endif
     288     2845980 :     n = recv(port->sock, ptr, len, 0);
     289             : #ifdef WIN32
     290             :     pgwin32_noblock = false;
     291             : #endif
     292             : 
     293     2845980 :     return n;
     294             : }
     295             : 
     296             : 
     297             : /*
     298             :  *  Write data to a secure connection.
     299             :  */
     300             : ssize_t
     301     1595632 : secure_write(Port *port, void *ptr, size_t len)
     302             : {
     303             :     ssize_t     n;
     304             :     int         waitfor;
     305             : 
     306             :     /* Deal with any already-pending interrupt condition. */
     307     1595632 :     ProcessClientWriteInterrupt(false);
     308             : 
     309     1618338 : retry:
     310     1618338 :     waitfor = 0;
     311             : #ifdef USE_SSL
     312     1618338 :     if (port->ssl_in_use)
     313             :     {
     314         338 :         n = be_tls_write(port, ptr, len, &waitfor);
     315             :     }
     316             :     else
     317             : #endif
     318             : #ifdef ENABLE_GSS
     319             :     if (port->gss && port->gss->enc)
     320             :     {
     321             :         n = be_gssapi_write(port, ptr, len);
     322             :         waitfor = WL_SOCKET_WRITEABLE;
     323             :     }
     324             :     else
     325             : #endif
     326             :     {
     327     1618000 :         n = secure_raw_write(port, ptr, len);
     328     1618000 :         waitfor = WL_SOCKET_WRITEABLE;
     329             :     }
     330             : 
     331     1618338 :     if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
     332             :     {
     333             :         WaitEvent   event;
     334             : 
     335             :         Assert(waitfor);
     336             : 
     337       22706 :         ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetSocketPos, waitfor, NULL);
     338             : 
     339       22706 :         WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
     340             :                          WAIT_EVENT_CLIENT_WRITE);
     341             : 
     342             :         /* See comments in secure_read. */
     343       22706 :         if (event.events & WL_POSTMASTER_DEATH)
     344           0 :             ereport(FATAL,
     345             :                     (errcode(ERRCODE_ADMIN_SHUTDOWN),
     346             :                      errmsg("terminating connection due to unexpected postmaster exit")));
     347             : 
     348             :         /* Handle interrupt. */
     349       22706 :         if (event.events & WL_LATCH_SET)
     350             :         {
     351          14 :             ResetLatch(MyLatch);
     352          14 :             ProcessClientWriteInterrupt(true);
     353             : 
     354             :             /*
     355             :              * We'll retry the write. Most likely it will return immediately
     356             :              * because there's still no buffer space available, and we'll wait
     357             :              * for the socket to become ready again.
     358             :              */
     359             :         }
     360       22706 :         goto retry;
     361             :     }
     362             : 
     363             :     /*
     364             :      * Process interrupts that happened during a successful (or non-blocking,
     365             :      * or hard-failed) write.
     366             :      */
     367     1595632 :     ProcessClientWriteInterrupt(false);
     368             : 
     369     1595632 :     return n;
     370             : }
     371             : 
     372             : ssize_t
     373     1619346 : secure_raw_write(Port *port, const void *ptr, size_t len)
     374             : {
     375             :     ssize_t     n;
     376             : 
     377             : #ifdef WIN32
     378             :     pgwin32_noblock = true;
     379             : #endif
     380     1619346 :     n = send(port->sock, ptr, len, 0);
     381             : #ifdef WIN32
     382             :     pgwin32_noblock = false;
     383             : #endif
     384             : 
     385     1619346 :     return n;
     386             : }

Generated by: LCOV version 1.14