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

Generated by: LCOV version 1.13