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

Generated by: LCOV version 1.14