LCOV - code coverage report
Current view: top level - src/backend/libpq - be-secure-openssl.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 310 501 61.9 %
Date: 2020-06-03 10:06:28 Functions: 28 30 93.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * be-secure-openssl.c
       4             :  *    functions for OpenSSL support in the backend.
       5             :  *
       6             :  *
       7             :  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
       8             :  * Portions Copyright (c) 1994, Regents of the University of California
       9             :  *
      10             :  *
      11             :  * IDENTIFICATION
      12             :  *    src/backend/libpq/be-secure-openssl.c
      13             :  *
      14             :  *-------------------------------------------------------------------------
      15             :  */
      16             : 
      17             : #include "postgres.h"
      18             : 
      19             : #include <sys/stat.h>
      20             : #include <signal.h>
      21             : #include <fcntl.h>
      22             : #include <ctype.h>
      23             : #include <sys/socket.h>
      24             : #include <unistd.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 <openssl/ssl.h>
      33             : #include <openssl/dh.h>
      34             : #include <openssl/conf.h>
      35             : #ifndef OPENSSL_NO_ECDH
      36             : #include <openssl/ec.h>
      37             : #endif
      38             : 
      39             : #include "common/openssl.h"
      40             : #include "libpq/libpq.h"
      41             : #include "miscadmin.h"
      42             : #include "pgstat.h"
      43             : #include "storage/fd.h"
      44             : #include "storage/latch.h"
      45             : #include "tcop/tcopprot.h"
      46             : #include "utils/memutils.h"
      47             : 
      48             : /* default init hook can be overridden by a shared library */
      49             : static void default_openssl_tls_init(SSL_CTX *context, bool isServerStart);
      50             : openssl_tls_init_hook_typ openssl_tls_init_hook = default_openssl_tls_init;
      51             : 
      52             : static int  my_sock_read(BIO *h, char *buf, int size);
      53             : static int  my_sock_write(BIO *h, const char *buf, int size);
      54             : static BIO_METHOD *my_BIO_s_socket(void);
      55             : static int  my_SSL_set_fd(Port *port, int fd);
      56             : 
      57             : static DH  *load_dh_file(char *filename, bool isServerStart);
      58             : static DH  *load_dh_buffer(const char *, size_t);
      59             : static int  ssl_external_passwd_cb(char *buf, int size, int rwflag, void *userdata);
      60             : static int  dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata);
      61             : static int  verify_cb(int, X509_STORE_CTX *);
      62             : static void info_cb(const SSL *ssl, int type, int args);
      63             : static bool initialize_dh(SSL_CTX *context, bool isServerStart);
      64             : static bool initialize_ecdh(SSL_CTX *context, bool isServerStart);
      65             : static const char *SSLerrmessage(unsigned long ecode);
      66             : 
      67             : static char *X509_NAME_to_cstring(X509_NAME *name);
      68             : 
      69             : static SSL_CTX *SSL_context = NULL;
      70             : static bool SSL_initialized = false;
      71             : static bool dummy_ssl_passwd_cb_called = false;
      72             : static bool ssl_is_server_start;
      73             : 
      74             : static int  ssl_protocol_version_to_openssl(int v);
      75             : 
      76             : /* ------------------------------------------------------------ */
      77             : /*                       Public interface                       */
      78             : /* ------------------------------------------------------------ */
      79             : 
      80             : int
      81          30 : be_tls_init(bool isServerStart)
      82             : {
      83          30 :     STACK_OF(X509_NAME) * root_cert_list = NULL;
      84             :     SSL_CTX    *context;
      85          30 :     int         ssl_ver_min = -1;
      86          30 :     int         ssl_ver_max = -1;
      87             : 
      88             :     /* This stuff need be done only once. */
      89          30 :     if (!SSL_initialized)
      90             :     {
      91             : #ifdef HAVE_OPENSSL_INIT_SSL
      92          30 :         OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
      93             : #else
      94             :         OPENSSL_config(NULL);
      95             :         SSL_library_init();
      96             :         SSL_load_error_strings();
      97             : #endif
      98          30 :         SSL_initialized = true;
      99             :     }
     100             : 
     101             :     /*
     102             :      * We use SSLv23_method() because it can negotiate use of the highest
     103             :      * mutually supported protocol version, while alternatives like
     104             :      * TLSv1_2_method() permit only one specific version.  Note that we don't
     105             :      * actually allow SSL v2 or v3, only TLS protocols (see below).
     106             :      */
     107          30 :     context = SSL_CTX_new(SSLv23_method());
     108          30 :     if (!context)
     109             :     {
     110           0 :         ereport(isServerStart ? FATAL : LOG,
     111             :                 (errmsg("could not create SSL context: %s",
     112             :                         SSLerrmessage(ERR_get_error()))));
     113           0 :         goto error;
     114             :     }
     115             : 
     116             :     /*
     117             :      * Disable OpenSSL's moving-write-buffer sanity check, because it causes
     118             :      * unnecessary failures in nonblocking send cases.
     119             :      */
     120          30 :     SSL_CTX_set_mode(context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
     121             : 
     122             :     /*
     123             :      * Call init hook (usually to set password callback)
     124             :      */
     125          30 :     (*openssl_tls_init_hook) (context, isServerStart);
     126             : 
     127             :     /* used by the callback */
     128          30 :     ssl_is_server_start = isServerStart;
     129             : 
     130             :     /*
     131             :      * Load and verify server's certificate and private key
     132             :      */
     133          30 :     if (SSL_CTX_use_certificate_chain_file(context, ssl_cert_file) != 1)
     134             :     {
     135           0 :         ereport(isServerStart ? FATAL : LOG,
     136             :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
     137             :                  errmsg("could not load server certificate file \"%s\": %s",
     138             :                         ssl_cert_file, SSLerrmessage(ERR_get_error()))));
     139           0 :         goto error;
     140             :     }
     141             : 
     142          30 :     if (!check_ssl_key_file_permissions(ssl_key_file, isServerStart))
     143           0 :         goto error;
     144             : 
     145             :     /*
     146             :      * OK, try to load the private key file.
     147             :      */
     148          30 :     dummy_ssl_passwd_cb_called = false;
     149             : 
     150          30 :     if (SSL_CTX_use_PrivateKey_file(context,
     151             :                                     ssl_key_file,
     152             :                                     SSL_FILETYPE_PEM) != 1)
     153             :     {
     154           4 :         if (dummy_ssl_passwd_cb_called)
     155           0 :             ereport(isServerStart ? FATAL : LOG,
     156             :                     (errcode(ERRCODE_CONFIG_FILE_ERROR),
     157             :                      errmsg("private key file \"%s\" cannot be reloaded because it requires a passphrase",
     158             :                             ssl_key_file)));
     159             :         else
     160           4 :             ereport(isServerStart ? FATAL : LOG,
     161             :                     (errcode(ERRCODE_CONFIG_FILE_ERROR),
     162             :                      errmsg("could not load private key file \"%s\": %s",
     163             :                             ssl_key_file, SSLerrmessage(ERR_get_error()))));
     164           0 :         goto error;
     165             :     }
     166             : 
     167          26 :     if (SSL_CTX_check_private_key(context) != 1)
     168             :     {
     169           0 :         ereport(isServerStart ? FATAL : LOG,
     170             :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
     171             :                  errmsg("check of private key failed: %s",
     172             :                         SSLerrmessage(ERR_get_error()))));
     173           0 :         goto error;
     174             :     }
     175             : 
     176          26 :     if (ssl_min_protocol_version)
     177             :     {
     178          26 :         ssl_ver_min = ssl_protocol_version_to_openssl(ssl_min_protocol_version);
     179             : 
     180          26 :         if (ssl_ver_min == -1)
     181             :         {
     182           0 :             ereport(isServerStart ? FATAL : LOG,
     183             :                     (errmsg("\"%s\" setting \"%s\" not supported by this build",
     184             :                             "ssl_min_protocol_version",
     185             :                             GetConfigOption("ssl_min_protocol_version",
     186             :                                             false, false))));
     187           0 :             goto error;
     188             :         }
     189             : 
     190          26 :         if (!SSL_CTX_set_min_proto_version(context, ssl_ver_min))
     191             :         {
     192           0 :             ereport(isServerStart ? FATAL : LOG,
     193             :                     (errmsg("could not set minimum SSL protocol version")));
     194           0 :             goto error;
     195             :         }
     196             :     }
     197             : 
     198          26 :     if (ssl_max_protocol_version)
     199             :     {
     200           2 :         ssl_ver_max = ssl_protocol_version_to_openssl(ssl_max_protocol_version);
     201             : 
     202           2 :         if (ssl_ver_max == -1)
     203             :         {
     204           0 :             ereport(isServerStart ? FATAL : LOG,
     205             :                     (errmsg("\"%s\" setting \"%s\" not supported by this build",
     206             :                             "ssl_max_protocol_version",
     207             :                             GetConfigOption("ssl_max_protocol_version",
     208             :                                             false, false))));
     209           0 :             goto error;
     210             :         }
     211             : 
     212           2 :         if (!SSL_CTX_set_max_proto_version(context, ssl_ver_max))
     213             :         {
     214           0 :             ereport(isServerStart ? FATAL : LOG,
     215             :                     (errmsg("could not set maximum SSL protocol version")));
     216           0 :             goto error;
     217             :         }
     218             :     }
     219             : 
     220             :     /* Check compatibility of min/max protocols */
     221          26 :     if (ssl_min_protocol_version &&
     222             :         ssl_max_protocol_version)
     223             :     {
     224             :         /*
     225             :          * No need to check for invalid values (-1) for each protocol number
     226             :          * as the code above would have already generated an error.
     227             :          */
     228           2 :         if (ssl_ver_min > ssl_ver_max)
     229             :         {
     230           2 :             ereport(isServerStart ? FATAL : LOG,
     231             :                     (errmsg("could not set SSL protocol version range"),
     232             :                      errdetail("\"%s\" cannot be higher than \"%s\"",
     233             :                                "ssl_min_protocol_version",
     234             :                                "ssl_max_protocol_version")));
     235           0 :             goto error;
     236             :         }
     237             :     }
     238             : 
     239             :     /* disallow SSL session tickets */
     240          24 :     SSL_CTX_set_options(context, SSL_OP_NO_TICKET);
     241             : 
     242             :     /* disallow SSL session caching, too */
     243          24 :     SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF);
     244             : 
     245             :     /* set up ephemeral DH and ECDH keys */
     246          24 :     if (!initialize_dh(context, isServerStart))
     247           0 :         goto error;
     248          24 :     if (!initialize_ecdh(context, isServerStart))
     249           0 :         goto error;
     250             : 
     251             :     /* set up the allowed cipher list */
     252          24 :     if (SSL_CTX_set_cipher_list(context, SSLCipherSuites) != 1)
     253             :     {
     254           0 :         ereport(isServerStart ? FATAL : LOG,
     255             :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
     256             :                  errmsg("could not set the cipher list (no valid ciphers available)")));
     257           0 :         goto error;
     258             :     }
     259             : 
     260             :     /* Let server choose order */
     261          24 :     if (SSLPreferServerCiphers)
     262          24 :         SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE);
     263             : 
     264             :     /*
     265             :      * Load CA store, so we can verify client certificates if needed.
     266             :      */
     267          24 :     if (ssl_ca_file[0])
     268             :     {
     269          32 :         if (SSL_CTX_load_verify_locations(context, ssl_ca_file, NULL) != 1 ||
     270          16 :             (root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL)
     271             :         {
     272           0 :             ereport(isServerStart ? FATAL : LOG,
     273             :                     (errcode(ERRCODE_CONFIG_FILE_ERROR),
     274             :                      errmsg("could not load root certificate file \"%s\": %s",
     275             :                             ssl_ca_file, SSLerrmessage(ERR_get_error()))));
     276           0 :             goto error;
     277             :         }
     278             :     }
     279             : 
     280             :     /*----------
     281             :      * Load the Certificate Revocation List (CRL).
     282             :      * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html
     283             :      *----------
     284             :      */
     285          24 :     if (ssl_crl_file[0])
     286             :     {
     287          16 :         X509_STORE *cvstore = SSL_CTX_get_cert_store(context);
     288             : 
     289          16 :         if (cvstore)
     290             :         {
     291             :             /* Set the flags to check against the complete CRL chain */
     292          16 :             if (X509_STORE_load_locations(cvstore, ssl_crl_file, NULL) == 1)
     293             :             {
     294          16 :                 X509_STORE_set_flags(cvstore,
     295             :                                      X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
     296             :             }
     297             :             else
     298             :             {
     299           0 :                 ereport(isServerStart ? FATAL : LOG,
     300             :                         (errcode(ERRCODE_CONFIG_FILE_ERROR),
     301             :                          errmsg("could not load SSL certificate revocation list file \"%s\": %s",
     302             :                                 ssl_crl_file, SSLerrmessage(ERR_get_error()))));
     303           0 :                 goto error;
     304             :             }
     305             :         }
     306             :     }
     307             : 
     308          24 :     if (ssl_ca_file[0])
     309             :     {
     310             :         /*
     311             :          * Always ask for SSL client cert, but don't fail if it's not
     312             :          * presented.  We might fail such connections later, depending on what
     313             :          * we find in pg_hba.conf.
     314             :          */
     315          16 :         SSL_CTX_set_verify(context,
     316             :                            (SSL_VERIFY_PEER |
     317             :                             SSL_VERIFY_CLIENT_ONCE),
     318             :                            verify_cb);
     319             : 
     320             :         /*
     321             :          * Tell OpenSSL to send the list of root certs we trust to clients in
     322             :          * CertificateRequests.  This lets a client with a keystore select the
     323             :          * appropriate client certificate to send to us.
     324             :          */
     325          16 :         SSL_CTX_set_client_CA_list(context, root_cert_list);
     326             :     }
     327             : 
     328             :     /*
     329             :      * Success!  Replace any existing SSL_context.
     330             :      */
     331          24 :     if (SSL_context)
     332           0 :         SSL_CTX_free(SSL_context);
     333             : 
     334          24 :     SSL_context = context;
     335             : 
     336             :     /*
     337             :      * Set flag to remember whether CA store has been loaded into SSL_context.
     338             :      */
     339          24 :     if (ssl_ca_file[0])
     340          16 :         ssl_loaded_verify_locations = true;
     341             :     else
     342           8 :         ssl_loaded_verify_locations = false;
     343             : 
     344          24 :     return 0;
     345             : 
     346           0 : error:
     347           0 :     if (context)
     348           0 :         SSL_CTX_free(context);
     349           0 :     return -1;
     350             : }
     351             : 
     352             : void
     353          78 : be_tls_destroy(void)
     354             : {
     355          78 :     if (SSL_context)
     356           0 :         SSL_CTX_free(SSL_context);
     357          78 :     SSL_context = NULL;
     358          78 :     ssl_loaded_verify_locations = false;
     359          78 : }
     360             : 
     361             : int
     362          96 : be_tls_open_server(Port *port)
     363             : {
     364             :     int         r;
     365             :     int         err;
     366             :     int         waitfor;
     367             :     unsigned long ecode;
     368             : 
     369             :     Assert(!port->ssl);
     370             :     Assert(!port->peer);
     371             : 
     372          96 :     if (!SSL_context)
     373             :     {
     374           0 :         ereport(COMMERROR,
     375             :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
     376             :                  errmsg("could not initialize SSL connection: SSL context not set up")));
     377           0 :         return -1;
     378             :     }
     379             : 
     380          96 :     if (!(port->ssl = SSL_new(SSL_context)))
     381             :     {
     382           0 :         ereport(COMMERROR,
     383             :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
     384             :                  errmsg("could not initialize SSL connection: %s",
     385             :                         SSLerrmessage(ERR_get_error()))));
     386           0 :         return -1;
     387             :     }
     388          96 :     if (!my_SSL_set_fd(port, port->sock))
     389             :     {
     390           0 :         ereport(COMMERROR,
     391             :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
     392             :                  errmsg("could not set SSL socket: %s",
     393             :                         SSLerrmessage(ERR_get_error()))));
     394           0 :         return -1;
     395             :     }
     396          96 :     port->ssl_in_use = true;
     397             : 
     398         164 : aloop:
     399             : 
     400             :     /*
     401             :      * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
     402             :      * queue.  In general, the current thread's error queue must be empty
     403             :      * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
     404             :      * not work reliably.  An extension may have failed to clear the
     405             :      * per-thread error queue following another call to an OpenSSL I/O
     406             :      * routine.
     407             :      */
     408         164 :     ERR_clear_error();
     409         164 :     r = SSL_accept(port->ssl);
     410         164 :     if (r <= 0)
     411             :     {
     412          90 :         err = SSL_get_error(port->ssl, r);
     413             : 
     414             :         /*
     415             :          * Other clients of OpenSSL in the backend may fail to call
     416             :          * ERR_get_error(), but we always do, so as to not cause problems for
     417             :          * OpenSSL clients that don't call ERR_clear_error() defensively.  Be
     418             :          * sure that this happens by calling now. SSL_get_error() relies on
     419             :          * the OpenSSL per-thread error queue being intact, so this is the
     420             :          * earliest possible point ERR_get_error() may be called.
     421             :          */
     422          90 :         ecode = ERR_get_error();
     423          90 :         switch (err)
     424             :         {
     425          68 :             case SSL_ERROR_WANT_READ:
     426             :             case SSL_ERROR_WANT_WRITE:
     427             :                 /* not allowed during connection establishment */
     428             :                 Assert(!port->noblock);
     429             : 
     430             :                 /*
     431             :                  * No need to care about timeouts/interrupts here. At this
     432             :                  * point authentication_timeout still employs
     433             :                  * StartupPacketTimeoutHandler() which directly exits.
     434             :                  */
     435          68 :                 if (err == SSL_ERROR_WANT_READ)
     436          68 :                     waitfor = WL_SOCKET_READABLE | WL_EXIT_ON_PM_DEATH;
     437             :                 else
     438           0 :                     waitfor = WL_SOCKET_WRITEABLE | WL_EXIT_ON_PM_DEATH;
     439             : 
     440          68 :                 (void) WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0,
     441             :                                          WAIT_EVENT_SSL_OPEN_SERVER);
     442          68 :                 goto aloop;
     443           8 :             case SSL_ERROR_SYSCALL:
     444           8 :                 if (r < 0)
     445           8 :                     ereport(COMMERROR,
     446             :                             (errcode_for_socket_access(),
     447             :                              errmsg("could not accept SSL connection: %m")));
     448             :                 else
     449           0 :                     ereport(COMMERROR,
     450             :                             (errcode(ERRCODE_PROTOCOL_VIOLATION),
     451             :                              errmsg("could not accept SSL connection: EOF detected")));
     452           8 :                 break;
     453          14 :             case SSL_ERROR_SSL:
     454          14 :                 ereport(COMMERROR,
     455             :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
     456             :                          errmsg("could not accept SSL connection: %s",
     457             :                                 SSLerrmessage(ecode))));
     458          14 :                 break;
     459           0 :             case SSL_ERROR_ZERO_RETURN:
     460           0 :                 ereport(COMMERROR,
     461             :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
     462             :                          errmsg("could not accept SSL connection: EOF detected")));
     463           0 :                 break;
     464           0 :             default:
     465           0 :                 ereport(COMMERROR,
     466             :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
     467             :                          errmsg("unrecognized SSL error code: %d",
     468             :                                 err)));
     469           0 :                 break;
     470             :         }
     471          22 :         return -1;
     472             :     }
     473             : 
     474             :     /* Get client certificate, if available. */
     475          74 :     port->peer = SSL_get_peer_certificate(port->ssl);
     476             : 
     477             :     /* and extract the Common Name from it. */
     478          74 :     port->peer_cn = NULL;
     479          74 :     port->peer_cert_valid = false;
     480          74 :     if (port->peer != NULL)
     481             :     {
     482             :         int         len;
     483             : 
     484          20 :         len = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer),
     485             :                                         NID_commonName, NULL, 0);
     486          20 :         if (len != -1)
     487             :         {
     488             :             char       *peer_cn;
     489             : 
     490          20 :             peer_cn = MemoryContextAlloc(TopMemoryContext, len + 1);
     491          20 :             r = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer),
     492             :                                           NID_commonName, peer_cn, len + 1);
     493          20 :             peer_cn[len] = '\0';
     494          20 :             if (r != len)
     495             :             {
     496             :                 /* shouldn't happen */
     497           0 :                 pfree(peer_cn);
     498           0 :                 return -1;
     499             :             }
     500             : 
     501             :             /*
     502             :              * Reject embedded NULLs in certificate common name to prevent
     503             :              * attacks like CVE-2009-4034.
     504             :              */
     505          20 :             if (len != strlen(peer_cn))
     506             :             {
     507           0 :                 ereport(COMMERROR,
     508             :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
     509             :                          errmsg("SSL certificate's common name contains embedded null")));
     510           0 :                 pfree(peer_cn);
     511           0 :                 return -1;
     512             :             }
     513             : 
     514          20 :             port->peer_cn = peer_cn;
     515             :         }
     516          20 :         port->peer_cert_valid = true;
     517             :     }
     518             : 
     519             :     /* set up debugging/info callback */
     520          74 :     SSL_CTX_set_info_callback(SSL_context, info_cb);
     521             : 
     522          74 :     return 0;
     523             : }
     524             : 
     525             : void
     526          96 : be_tls_close(Port *port)
     527             : {
     528          96 :     if (port->ssl)
     529             :     {
     530          96 :         SSL_shutdown(port->ssl);
     531          96 :         SSL_free(port->ssl);
     532          96 :         port->ssl = NULL;
     533          96 :         port->ssl_in_use = false;
     534             :     }
     535             : 
     536          96 :     if (port->peer)
     537             :     {
     538          20 :         X509_free(port->peer);
     539          20 :         port->peer = NULL;
     540             :     }
     541             : 
     542          96 :     if (port->peer_cn)
     543             :     {
     544          20 :         pfree(port->peer_cn);
     545          20 :         port->peer_cn = NULL;
     546             :     }
     547          96 : }
     548             : 
     549             : ssize_t
     550         246 : be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
     551             : {
     552             :     ssize_t     n;
     553             :     int         err;
     554             :     unsigned long ecode;
     555             : 
     556         246 :     errno = 0;
     557         246 :     ERR_clear_error();
     558         246 :     n = SSL_read(port->ssl, ptr, len);
     559         246 :     err = SSL_get_error(port->ssl, n);
     560         246 :     ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
     561         246 :     switch (err)
     562             :     {
     563         206 :         case SSL_ERROR_NONE:
     564             :             /* a-ok */
     565         206 :             break;
     566          34 :         case SSL_ERROR_WANT_READ:
     567          34 :             *waitfor = WL_SOCKET_READABLE;
     568          34 :             errno = EWOULDBLOCK;
     569          34 :             n = -1;
     570          34 :             break;
     571           0 :         case SSL_ERROR_WANT_WRITE:
     572           0 :             *waitfor = WL_SOCKET_WRITEABLE;
     573           0 :             errno = EWOULDBLOCK;
     574           0 :             n = -1;
     575           0 :             break;
     576           0 :         case SSL_ERROR_SYSCALL:
     577             :             /* leave it to caller to ereport the value of errno */
     578           0 :             if (n != -1)
     579             :             {
     580           0 :                 errno = ECONNRESET;
     581           0 :                 n = -1;
     582             :             }
     583           0 :             break;
     584           0 :         case SSL_ERROR_SSL:
     585           0 :             ereport(COMMERROR,
     586             :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
     587             :                      errmsg("SSL error: %s", SSLerrmessage(ecode))));
     588           0 :             errno = ECONNRESET;
     589           0 :             n = -1;
     590           0 :             break;
     591           6 :         case SSL_ERROR_ZERO_RETURN:
     592             :             /* connection was cleanly shut down by peer */
     593           6 :             n = 0;
     594           6 :             break;
     595           0 :         default:
     596           0 :             ereport(COMMERROR,
     597             :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
     598             :                      errmsg("unrecognized SSL error code: %d",
     599             :                             err)));
     600           0 :             errno = ECONNRESET;
     601           0 :             n = -1;
     602           0 :             break;
     603             :     }
     604             : 
     605         246 :     return n;
     606             : }
     607             : 
     608             : ssize_t
     609         144 : be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
     610             : {
     611             :     ssize_t     n;
     612             :     int         err;
     613             :     unsigned long ecode;
     614             : 
     615         144 :     errno = 0;
     616         144 :     ERR_clear_error();
     617         144 :     n = SSL_write(port->ssl, ptr, len);
     618         144 :     err = SSL_get_error(port->ssl, n);
     619         144 :     ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
     620         144 :     switch (err)
     621             :     {
     622         144 :         case SSL_ERROR_NONE:
     623             :             /* a-ok */
     624         144 :             break;
     625           0 :         case SSL_ERROR_WANT_READ:
     626           0 :             *waitfor = WL_SOCKET_READABLE;
     627           0 :             errno = EWOULDBLOCK;
     628           0 :             n = -1;
     629           0 :             break;
     630           0 :         case SSL_ERROR_WANT_WRITE:
     631           0 :             *waitfor = WL_SOCKET_WRITEABLE;
     632           0 :             errno = EWOULDBLOCK;
     633           0 :             n = -1;
     634           0 :             break;
     635           0 :         case SSL_ERROR_SYSCALL:
     636             :             /* leave it to caller to ereport the value of errno */
     637           0 :             if (n != -1)
     638             :             {
     639           0 :                 errno = ECONNRESET;
     640           0 :                 n = -1;
     641             :             }
     642           0 :             break;
     643           0 :         case SSL_ERROR_SSL:
     644           0 :             ereport(COMMERROR,
     645             :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
     646             :                      errmsg("SSL error: %s", SSLerrmessage(ecode))));
     647           0 :             errno = ECONNRESET;
     648           0 :             n = -1;
     649           0 :             break;
     650           0 :         case SSL_ERROR_ZERO_RETURN:
     651             : 
     652             :             /*
     653             :              * the SSL connection was closed, leave it to the caller to
     654             :              * ereport it
     655             :              */
     656           0 :             errno = ECONNRESET;
     657           0 :             n = -1;
     658           0 :             break;
     659           0 :         default:
     660           0 :             ereport(COMMERROR,
     661             :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
     662             :                      errmsg("unrecognized SSL error code: %d",
     663             :                             err)));
     664           0 :             errno = ECONNRESET;
     665           0 :             n = -1;
     666           0 :             break;
     667             :     }
     668             : 
     669         144 :     return n;
     670             : }
     671             : 
     672             : /* ------------------------------------------------------------ */
     673             : /*                      Internal functions                      */
     674             : /* ------------------------------------------------------------ */
     675             : 
     676             : /*
     677             :  * Private substitute BIO: this does the sending and receiving using send() and
     678             :  * recv() instead. This is so that we can enable and disable interrupts
     679             :  * just while calling recv(). We cannot have interrupts occurring while
     680             :  * the bulk of OpenSSL runs, because it uses malloc() and possibly other
     681             :  * non-reentrant libc facilities. We also need to call send() and recv()
     682             :  * directly so it gets passed through the socket/signals layer on Win32.
     683             :  *
     684             :  * These functions are closely modelled on the standard socket BIO in OpenSSL;
     685             :  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
     686             :  * XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons
     687             :  * to retry; do we need to adopt their logic for that?
     688             :  */
     689             : 
     690             : #ifndef HAVE_BIO_GET_DATA
     691             : #define BIO_get_data(bio) (bio->ptr)
     692             : #define BIO_set_data(bio, data) (bio->ptr = data)
     693             : #endif
     694             : 
     695             : static BIO_METHOD *my_bio_methods = NULL;
     696             : 
     697             : static int
     698        1426 : my_sock_read(BIO *h, char *buf, int size)
     699             : {
     700        1426 :     int         res = 0;
     701             : 
     702        1426 :     if (buf != NULL)
     703             :     {
     704        1426 :         res = secure_raw_read(((Port *) BIO_get_data(h)), buf, size);
     705        1426 :         BIO_clear_retry_flags(h);
     706        1426 :         if (res <= 0)
     707             :         {
     708             :             /* If we were interrupted, tell caller to retry */
     709         110 :             if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
     710             :             {
     711         102 :                 BIO_set_retry_read(h);
     712             :             }
     713             :         }
     714             :     }
     715             : 
     716        1426 :     return res;
     717             : }
     718             : 
     719             : static int
     720         540 : my_sock_write(BIO *h, const char *buf, int size)
     721             : {
     722         540 :     int         res = 0;
     723             : 
     724         540 :     res = secure_raw_write(((Port *) BIO_get_data(h)), buf, size);
     725         540 :     BIO_clear_retry_flags(h);
     726         540 :     if (res <= 0)
     727             :     {
     728             :         /* If we were interrupted, tell caller to retry */
     729           8 :         if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
     730             :         {
     731           0 :             BIO_set_retry_write(h);
     732             :         }
     733             :     }
     734             : 
     735         540 :     return res;
     736             : }
     737             : 
     738             : static BIO_METHOD *
     739          96 : my_BIO_s_socket(void)
     740             : {
     741          96 :     if (!my_bio_methods)
     742             :     {
     743          96 :         BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
     744             : #ifdef HAVE_BIO_METH_NEW
     745             :         int         my_bio_index;
     746             : 
     747          96 :         my_bio_index = BIO_get_new_index();
     748          96 :         if (my_bio_index == -1)
     749           0 :             return NULL;
     750          96 :         my_bio_methods = BIO_meth_new(my_bio_index, "PostgreSQL backend socket");
     751          96 :         if (!my_bio_methods)
     752           0 :             return NULL;
     753         192 :         if (!BIO_meth_set_write(my_bio_methods, my_sock_write) ||
     754         192 :             !BIO_meth_set_read(my_bio_methods, my_sock_read) ||
     755         192 :             !BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) ||
     756         192 :             !BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) ||
     757         192 :             !BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) ||
     758         192 :             !BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) ||
     759         192 :             !BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) ||
     760          96 :             !BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom)))
     761             :         {
     762           0 :             BIO_meth_free(my_bio_methods);
     763           0 :             my_bio_methods = NULL;
     764           0 :             return NULL;
     765             :         }
     766             : #else
     767             :         my_bio_methods = malloc(sizeof(BIO_METHOD));
     768             :         if (!my_bio_methods)
     769             :             return NULL;
     770             :         memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
     771             :         my_bio_methods->bread = my_sock_read;
     772             :         my_bio_methods->bwrite = my_sock_write;
     773             : #endif
     774             :     }
     775          96 :     return my_bio_methods;
     776             : }
     777             : 
     778             : /* This should exactly match OpenSSL's SSL_set_fd except for using my BIO */
     779             : static int
     780          96 : my_SSL_set_fd(Port *port, int fd)
     781             : {
     782          96 :     int         ret = 0;
     783             :     BIO        *bio;
     784             :     BIO_METHOD *bio_method;
     785             : 
     786          96 :     bio_method = my_BIO_s_socket();
     787          96 :     if (bio_method == NULL)
     788             :     {
     789           0 :         SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
     790           0 :         goto err;
     791             :     }
     792          96 :     bio = BIO_new(bio_method);
     793             : 
     794          96 :     if (bio == NULL)
     795             :     {
     796           0 :         SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
     797           0 :         goto err;
     798             :     }
     799          96 :     BIO_set_data(bio, port);
     800             : 
     801          96 :     BIO_set_fd(bio, fd, BIO_NOCLOSE);
     802          96 :     SSL_set_bio(port->ssl, bio, bio);
     803          96 :     ret = 1;
     804          96 : err:
     805          96 :     return ret;
     806             : }
     807             : 
     808             : /*
     809             :  *  Load precomputed DH parameters.
     810             :  *
     811             :  *  To prevent "downgrade" attacks, we perform a number of checks
     812             :  *  to verify that the DBA-generated DH parameters file contains
     813             :  *  what we expect it to contain.
     814             :  */
     815             : static DH  *
     816           0 : load_dh_file(char *filename, bool isServerStart)
     817             : {
     818             :     FILE       *fp;
     819           0 :     DH         *dh = NULL;
     820             :     int         codes;
     821             : 
     822             :     /* attempt to open file.  It's not an error if it doesn't exist. */
     823           0 :     if ((fp = AllocateFile(filename, "r")) == NULL)
     824             :     {
     825           0 :         ereport(isServerStart ? FATAL : LOG,
     826             :                 (errcode_for_file_access(),
     827             :                  errmsg("could not open DH parameters file \"%s\": %m",
     828             :                         filename)));
     829           0 :         return NULL;
     830             :     }
     831             : 
     832           0 :     dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
     833           0 :     FreeFile(fp);
     834             : 
     835           0 :     if (dh == NULL)
     836             :     {
     837           0 :         ereport(isServerStart ? FATAL : LOG,
     838             :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
     839             :                  errmsg("could not load DH parameters file: %s",
     840             :                         SSLerrmessage(ERR_get_error()))));
     841           0 :         return NULL;
     842             :     }
     843             : 
     844             :     /* make sure the DH parameters are usable */
     845           0 :     if (DH_check(dh, &codes) == 0)
     846             :     {
     847           0 :         ereport(isServerStart ? FATAL : LOG,
     848             :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
     849             :                  errmsg("invalid DH parameters: %s",
     850             :                         SSLerrmessage(ERR_get_error()))));
     851           0 :         return NULL;
     852             :     }
     853           0 :     if (codes & DH_CHECK_P_NOT_PRIME)
     854             :     {
     855           0 :         ereport(isServerStart ? FATAL : LOG,
     856             :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
     857             :                  errmsg("invalid DH parameters: p is not prime")));
     858           0 :         return NULL;
     859             :     }
     860           0 :     if ((codes & DH_NOT_SUITABLE_GENERATOR) &&
     861           0 :         (codes & DH_CHECK_P_NOT_SAFE_PRIME))
     862             :     {
     863           0 :         ereport(isServerStart ? FATAL : LOG,
     864             :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
     865             :                  errmsg("invalid DH parameters: neither suitable generator or safe prime")));
     866           0 :         return NULL;
     867             :     }
     868             : 
     869           0 :     return dh;
     870             : }
     871             : 
     872             : /*
     873             :  *  Load hardcoded DH parameters.
     874             :  *
     875             :  *  To prevent problems if the DH parameters files don't even
     876             :  *  exist, we can load DH parameters hardcoded into this file.
     877             :  */
     878             : static DH  *
     879          24 : load_dh_buffer(const char *buffer, size_t len)
     880             : {
     881             :     BIO        *bio;
     882          24 :     DH         *dh = NULL;
     883             : 
     884          24 :     bio = BIO_new_mem_buf(unconstify(char *, buffer), len);
     885          24 :     if (bio == NULL)
     886           0 :         return NULL;
     887          24 :     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
     888          24 :     if (dh == NULL)
     889           0 :         ereport(DEBUG2,
     890             :                 (errmsg_internal("DH load buffer: %s",
     891             :                                  SSLerrmessage(ERR_get_error()))));
     892          24 :     BIO_free(bio);
     893             : 
     894          24 :     return dh;
     895             : }
     896             : 
     897             : /*
     898             :  *  Passphrase collection callback using ssl_passphrase_command
     899             :  */
     900             : static int
     901           8 : ssl_external_passwd_cb(char *buf, int size, int rwflag, void *userdata)
     902             : {
     903             :     /* same prompt as OpenSSL uses internally */
     904           8 :     const char *prompt = "Enter PEM pass phrase:";
     905             : 
     906             :     Assert(rwflag == 0);
     907             : 
     908           8 :     return run_ssl_passphrase_command(prompt, ssl_is_server_start, buf, size);
     909             : }
     910             : 
     911             : /*
     912             :  * Dummy passphrase callback
     913             :  *
     914             :  * If OpenSSL is told to use a passphrase-protected server key, by default
     915             :  * it will issue a prompt on /dev/tty and try to read a key from there.
     916             :  * That's no good during a postmaster SIGHUP cycle, not to mention SSL context
     917             :  * reload in an EXEC_BACKEND postmaster child.  So override it with this dummy
     918             :  * function that just returns an empty passphrase, guaranteeing failure.
     919             :  */
     920             : static int
     921           0 : dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
     922             : {
     923             :     /* Set flag to change the error message we'll report */
     924           0 :     dummy_ssl_passwd_cb_called = true;
     925             :     /* And return empty string */
     926             :     Assert(size > 0);
     927           0 :     buf[0] = '\0';
     928           0 :     return 0;
     929             : }
     930             : 
     931             : /*
     932             :  *  Certificate verification callback
     933             :  *
     934             :  *  This callback allows us to log intermediate problems during
     935             :  *  verification, but for now we'll see if the final error message
     936             :  *  contains enough information.
     937             :  *
     938             :  *  This callback also allows us to override the default acceptance
     939             :  *  criteria (e.g., accepting self-signed or expired certs), but
     940             :  *  for now we accept the default checks.
     941             :  */
     942             : static int
     943          62 : verify_cb(int ok, X509_STORE_CTX *ctx)
     944             : {
     945          62 :     return ok;
     946             : }
     947             : 
     948             : /*
     949             :  *  This callback is used to copy SSL information messages
     950             :  *  into the PostgreSQL log.
     951             :  */
     952             : static void
     953          76 : info_cb(const SSL *ssl, int type, int args)
     954             : {
     955          76 :     switch (type)
     956             :     {
     957           0 :         case SSL_CB_HANDSHAKE_START:
     958           0 :             ereport(DEBUG4,
     959             :                     (errmsg_internal("SSL: handshake start")));
     960           0 :             break;
     961           0 :         case SSL_CB_HANDSHAKE_DONE:
     962           0 :             ereport(DEBUG4,
     963             :                     (errmsg_internal("SSL: handshake done")));
     964           0 :             break;
     965           0 :         case SSL_CB_ACCEPT_LOOP:
     966           0 :             ereport(DEBUG4,
     967             :                     (errmsg_internal("SSL: accept loop")));
     968           0 :             break;
     969           0 :         case SSL_CB_ACCEPT_EXIT:
     970           0 :             ereport(DEBUG4,
     971             :                     (errmsg_internal("SSL: accept exit (%d)", args)));
     972           0 :             break;
     973           0 :         case SSL_CB_CONNECT_LOOP:
     974           0 :             ereport(DEBUG4,
     975             :                     (errmsg_internal("SSL: connect loop")));
     976           0 :             break;
     977           0 :         case SSL_CB_CONNECT_EXIT:
     978           0 :             ereport(DEBUG4,
     979             :                     (errmsg_internal("SSL: connect exit (%d)", args)));
     980           0 :             break;
     981           6 :         case SSL_CB_READ_ALERT:
     982           6 :             ereport(DEBUG4,
     983             :                     (errmsg_internal("SSL: read alert (0x%04x)", args)));
     984           6 :             break;
     985          70 :         case SSL_CB_WRITE_ALERT:
     986          70 :             ereport(DEBUG4,
     987             :                     (errmsg_internal("SSL: write alert (0x%04x)", args)));
     988          70 :             break;
     989             :     }
     990          76 : }
     991             : 
     992             : /*
     993             :  * Set DH parameters for generating ephemeral DH keys.  The
     994             :  * DH parameters can take a long time to compute, so they must be
     995             :  * precomputed.
     996             :  *
     997             :  * Since few sites will bother to create a parameter file, we also
     998             :  * provide a fallback to the parameters provided by the OpenSSL
     999             :  * project.
    1000             :  *
    1001             :  * These values can be static (once loaded or computed) since the
    1002             :  * OpenSSL library can efficiently generate random keys from the
    1003             :  * information provided.
    1004             :  */
    1005             : static bool
    1006          24 : initialize_dh(SSL_CTX *context, bool isServerStart)
    1007             : {
    1008          24 :     DH         *dh = NULL;
    1009             : 
    1010          24 :     SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE);
    1011             : 
    1012          24 :     if (ssl_dh_params_file[0])
    1013           0 :         dh = load_dh_file(ssl_dh_params_file, isServerStart);
    1014          24 :     if (!dh)
    1015          24 :         dh = load_dh_buffer(FILE_DH2048, sizeof(FILE_DH2048));
    1016          24 :     if (!dh)
    1017             :     {
    1018           0 :         ereport(isServerStart ? FATAL : LOG,
    1019             :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
    1020             :                  errmsg("DH: could not load DH parameters")));
    1021           0 :         return false;
    1022             :     }
    1023             : 
    1024          24 :     if (SSL_CTX_set_tmp_dh(context, dh) != 1)
    1025             :     {
    1026           0 :         ereport(isServerStart ? FATAL : LOG,
    1027             :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
    1028             :                  errmsg("DH: could not set DH parameters: %s",
    1029             :                         SSLerrmessage(ERR_get_error()))));
    1030           0 :         DH_free(dh);
    1031           0 :         return false;
    1032             :     }
    1033             : 
    1034          24 :     DH_free(dh);
    1035          24 :     return true;
    1036             : }
    1037             : 
    1038             : /*
    1039             :  * Set ECDH parameters for generating ephemeral Elliptic Curve DH
    1040             :  * keys.  This is much simpler than the DH parameters, as we just
    1041             :  * need to provide the name of the curve to OpenSSL.
    1042             :  */
    1043             : static bool
    1044          24 : initialize_ecdh(SSL_CTX *context, bool isServerStart)
    1045             : {
    1046             : #ifndef OPENSSL_NO_ECDH
    1047             :     EC_KEY     *ecdh;
    1048             :     int         nid;
    1049             : 
    1050          24 :     nid = OBJ_sn2nid(SSLECDHCurve);
    1051          24 :     if (!nid)
    1052             :     {
    1053           0 :         ereport(isServerStart ? FATAL : LOG,
    1054             :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
    1055             :                  errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve)));
    1056           0 :         return false;
    1057             :     }
    1058             : 
    1059          24 :     ecdh = EC_KEY_new_by_curve_name(nid);
    1060          24 :     if (!ecdh)
    1061             :     {
    1062           0 :         ereport(isServerStart ? FATAL : LOG,
    1063             :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
    1064             :                  errmsg("ECDH: could not create key")));
    1065           0 :         return false;
    1066             :     }
    1067             : 
    1068          24 :     SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
    1069          24 :     SSL_CTX_set_tmp_ecdh(context, ecdh);
    1070          24 :     EC_KEY_free(ecdh);
    1071             : #endif
    1072             : 
    1073          24 :     return true;
    1074             : }
    1075             : 
    1076             : /*
    1077             :  * Obtain reason string for passed SSL errcode
    1078             :  *
    1079             :  * ERR_get_error() is used by caller to get errcode to pass here.
    1080             :  *
    1081             :  * Some caution is needed here since ERR_reason_error_string will
    1082             :  * return NULL if it doesn't recognize the error code.  We don't
    1083             :  * want to return NULL ever.
    1084             :  */
    1085             : static const char *
    1086          18 : SSLerrmessage(unsigned long ecode)
    1087             : {
    1088             :     const char *errreason;
    1089             :     static char errbuf[36];
    1090             : 
    1091          18 :     if (ecode == 0)
    1092           0 :         return _("no SSL error reported");
    1093          18 :     errreason = ERR_reason_error_string(ecode);
    1094          18 :     if (errreason != NULL)
    1095          18 :         return errreason;
    1096           0 :     snprintf(errbuf, sizeof(errbuf), _("SSL error code %lu"), ecode);
    1097           0 :     return errbuf;
    1098             : }
    1099             : 
    1100             : int
    1101         124 : be_tls_get_cipher_bits(Port *port)
    1102             : {
    1103             :     int         bits;
    1104             : 
    1105         124 :     if (port->ssl)
    1106             :     {
    1107         124 :         SSL_get_cipher_bits(port->ssl, &bits);
    1108         124 :         return bits;
    1109             :     }
    1110             :     else
    1111           0 :         return 0;
    1112             : }
    1113             : 
    1114             : bool
    1115         124 : be_tls_get_compression(Port *port)
    1116             : {
    1117         124 :     if (port->ssl)
    1118         124 :         return (SSL_get_current_compression(port->ssl) != NULL);
    1119             :     else
    1120           0 :         return false;
    1121             : }
    1122             : 
    1123             : const char *
    1124         124 : be_tls_get_version(Port *port)
    1125             : {
    1126         124 :     if (port->ssl)
    1127         124 :         return SSL_get_version(port->ssl);
    1128             :     else
    1129           0 :         return NULL;
    1130             : }
    1131             : 
    1132             : const char *
    1133         124 : be_tls_get_cipher(Port *port)
    1134             : {
    1135         124 :     if (port->ssl)
    1136         124 :         return SSL_get_cipher(port->ssl);
    1137             :     else
    1138           0 :         return NULL;
    1139             : }
    1140             : 
    1141             : void
    1142          62 : be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len)
    1143             : {
    1144          62 :     if (port->peer)
    1145          16 :         strlcpy(ptr, X509_NAME_to_cstring(X509_get_subject_name(port->peer)), len);
    1146             :     else
    1147          46 :         ptr[0] = '\0';
    1148          62 : }
    1149             : 
    1150             : void
    1151          62 : be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len)
    1152             : {
    1153          62 :     if (port->peer)
    1154          16 :         strlcpy(ptr, X509_NAME_to_cstring(X509_get_issuer_name(port->peer)), len);
    1155             :     else
    1156          46 :         ptr[0] = '\0';
    1157          62 : }
    1158             : 
    1159             : void
    1160          62 : be_tls_get_peer_serial(Port *port, char *ptr, size_t len)
    1161             : {
    1162          62 :     if (port->peer)
    1163             :     {
    1164             :         ASN1_INTEGER *serial;
    1165             :         BIGNUM     *b;
    1166             :         char       *decimal;
    1167             : 
    1168          16 :         serial = X509_get_serialNumber(port->peer);
    1169          16 :         b = ASN1_INTEGER_to_BN(serial, NULL);
    1170          16 :         decimal = BN_bn2dec(b);
    1171             : 
    1172          16 :         BN_free(b);
    1173          16 :         strlcpy(ptr, decimal, len);
    1174          16 :         OPENSSL_free(decimal);
    1175             :     }
    1176             :     else
    1177          46 :         ptr[0] = '\0';
    1178          62 : }
    1179             : 
    1180             : #ifdef HAVE_X509_GET_SIGNATURE_NID
    1181             : char *
    1182           4 : be_tls_get_certificate_hash(Port *port, size_t *len)
    1183             : {
    1184             :     X509       *server_cert;
    1185             :     char       *cert_hash;
    1186           4 :     const EVP_MD *algo_type = NULL;
    1187             :     unsigned char hash[EVP_MAX_MD_SIZE];    /* size for SHA-512 */
    1188             :     unsigned int hash_size;
    1189             :     int         algo_nid;
    1190             : 
    1191           4 :     *len = 0;
    1192           4 :     server_cert = SSL_get_certificate(port->ssl);
    1193           4 :     if (server_cert == NULL)
    1194           0 :         return NULL;
    1195             : 
    1196             :     /*
    1197             :      * Get the signature algorithm of the certificate to determine the hash
    1198             :      * algorithm to use for the result.
    1199             :      */
    1200           4 :     if (!OBJ_find_sigid_algs(X509_get_signature_nid(server_cert),
    1201             :                              &algo_nid, NULL))
    1202           0 :         elog(ERROR, "could not determine server certificate signature algorithm");
    1203             : 
    1204             :     /*
    1205             :      * The TLS server's certificate bytes need to be hashed with SHA-256 if
    1206             :      * its signature algorithm is MD5 or SHA-1 as per RFC 5929
    1207             :      * (https://tools.ietf.org/html/rfc5929#section-4.1).  If something else
    1208             :      * is used, the same hash as the signature algorithm is used.
    1209             :      */
    1210           4 :     switch (algo_nid)
    1211             :     {
    1212           0 :         case NID_md5:
    1213             :         case NID_sha1:
    1214           0 :             algo_type = EVP_sha256();
    1215           0 :             break;
    1216           4 :         default:
    1217           4 :             algo_type = EVP_get_digestbynid(algo_nid);
    1218           4 :             if (algo_type == NULL)
    1219           0 :                 elog(ERROR, "could not find digest for NID %s",
    1220             :                      OBJ_nid2sn(algo_nid));
    1221           4 :             break;
    1222             :     }
    1223             : 
    1224             :     /* generate and save the certificate hash */
    1225           4 :     if (!X509_digest(server_cert, algo_type, hash, &hash_size))
    1226           0 :         elog(ERROR, "could not generate server certificate hash");
    1227             : 
    1228           4 :     cert_hash = palloc(hash_size);
    1229           4 :     memcpy(cert_hash, hash, hash_size);
    1230           4 :     *len = hash_size;
    1231             : 
    1232           4 :     return cert_hash;
    1233             : }
    1234             : #endif
    1235             : 
    1236             : /*
    1237             :  * Convert an X509 subject name to a cstring.
    1238             :  *
    1239             :  */
    1240             : static char *
    1241          32 : X509_NAME_to_cstring(X509_NAME *name)
    1242             : {
    1243          32 :     BIO        *membuf = BIO_new(BIO_s_mem());
    1244             :     int         i,
    1245             :                 nid,
    1246          32 :                 count = X509_NAME_entry_count(name);
    1247             :     X509_NAME_ENTRY *e;
    1248             :     ASN1_STRING *v;
    1249             :     const char *field_name;
    1250             :     size_t      size;
    1251             :     char        nullterm;
    1252             :     char       *sp;
    1253             :     char       *dp;
    1254             :     char       *result;
    1255             : 
    1256          32 :     (void) BIO_set_close(membuf, BIO_CLOSE);
    1257          64 :     for (i = 0; i < count; i++)
    1258             :     {
    1259          32 :         e = X509_NAME_get_entry(name, i);
    1260          32 :         nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e));
    1261          32 :         v = X509_NAME_ENTRY_get_data(e);
    1262          32 :         field_name = OBJ_nid2sn(nid);
    1263          32 :         if (!field_name)
    1264           0 :             field_name = OBJ_nid2ln(nid);
    1265          32 :         BIO_printf(membuf, "/%s=", field_name);
    1266          32 :         ASN1_STRING_print_ex(membuf, v,
    1267             :                              ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB)
    1268             :                               | ASN1_STRFLGS_UTF8_CONVERT));
    1269             :     }
    1270             : 
    1271             :     /* ensure null termination of the BIO's content */
    1272          32 :     nullterm = '\0';
    1273          32 :     BIO_write(membuf, &nullterm, 1);
    1274          32 :     size = BIO_get_mem_data(membuf, &sp);
    1275          32 :     dp = pg_any_to_server(sp, size - 1, PG_UTF8);
    1276             : 
    1277          32 :     result = pstrdup(dp);
    1278          32 :     if (dp != sp)
    1279           0 :         pfree(dp);
    1280          32 :     BIO_free(membuf);
    1281             : 
    1282          32 :     return result;
    1283             : }
    1284             : 
    1285             : /*
    1286             :  * Convert TLS protocol version GUC enum to OpenSSL values
    1287             :  *
    1288             :  * This is a straightforward one-to-one mapping, but doing it this way makes
    1289             :  * guc.c independent of OpenSSL availability and version.
    1290             :  *
    1291             :  * If a version is passed that is not supported by the current OpenSSL
    1292             :  * version, then we return -1.  If a nonnegative value is returned,
    1293             :  * subsequent code can assume it's working with a supported version.
    1294             :  *
    1295             :  * Note: this is rather similar to libpq's routine in fe-secure-openssl.c,
    1296             :  * so make sure to update both routines if changing this one.
    1297             :  */
    1298             : static int
    1299          28 : ssl_protocol_version_to_openssl(int v)
    1300             : {
    1301          28 :     switch (v)
    1302             :     {
    1303           0 :         case PG_TLS_ANY:
    1304           0 :             return 0;
    1305           0 :         case PG_TLS1_VERSION:
    1306           0 :             return TLS1_VERSION;
    1307           2 :         case PG_TLS1_1_VERSION:
    1308             : #ifdef TLS1_1_VERSION
    1309           2 :             return TLS1_1_VERSION;
    1310             : #else
    1311             :             break;
    1312             : #endif
    1313          26 :         case PG_TLS1_2_VERSION:
    1314             : #ifdef TLS1_2_VERSION
    1315          26 :             return TLS1_2_VERSION;
    1316             : #else
    1317             :             break;
    1318             : #endif
    1319           0 :         case PG_TLS1_3_VERSION:
    1320             : #ifdef TLS1_3_VERSION
    1321           0 :             return TLS1_3_VERSION;
    1322             : #else
    1323             :             break;
    1324             : #endif
    1325             :     }
    1326             : 
    1327           0 :     return -1;
    1328             : }
    1329             : 
    1330             : 
    1331             : static void
    1332          24 : default_openssl_tls_init(SSL_CTX *context, bool isServerStart)
    1333             : {
    1334          24 :     if (isServerStart)
    1335             :     {
    1336          24 :         if (ssl_passphrase_command[0])
    1337           8 :             SSL_CTX_set_default_passwd_cb(context, ssl_external_passwd_cb);
    1338             :     }
    1339             :     else
    1340             :     {
    1341           0 :         if (ssl_passphrase_command[0] && ssl_passphrase_command_supports_reload)
    1342           0 :             SSL_CTX_set_default_passwd_cb(context, ssl_external_passwd_cb);
    1343             :         else
    1344             : 
    1345             :             /*
    1346             :              * If reloading and no external command is configured, override
    1347             :              * OpenSSL's default handling of passphrase-protected files,
    1348             :              * because we don't want to prompt for a passphrase in an
    1349             :              * already-running server.
    1350             :              */
    1351           0 :             SSL_CTX_set_default_passwd_cb(context, dummy_ssl_passwd_cb);
    1352             :     }
    1353          24 : }

Generated by: LCOV version 1.13