LCOV - differential code coverage report
Current view: top level - src/backend/libpq - be-secure-openssl.c (source / functions) Coverage Total Hit UNC UBC GBC GNC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 64.2 % 636 408 5 223 3 16 389
Current Date: 2024-04-14 14:21:10 Functions: 90.6 % 32 29 3 2 27
Baseline: 16@8cea358b128 Branches: 36.6 % 500 183 15 302 4 11 168
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 69.6 % 23 16 5 2 16
(120,180] days: 71.4 % 7 5 2 5
(180,240] days: 18.2 % 11 2 9 2
(240..) days: 64.7 % 595 385 210 3 382
Function coverage date bins:
[..60] days: 100.0 % 1 1 1
(240..) days: 90.3 % 31 28 3 1 27
Branch coverage date bins:
[..60] days: 39.3 % 28 11 15 2 11
(120,180] days: 16.7 % 12 2 10 2
(180,240] days: 20.0 % 10 2 8 2
(240..) days: 37.3 % 450 168 282 4 164

 Age         Owner                    Branch data    TLA  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-2024, 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                 :                : #include <netinet/tcp.h>
                                 28                 :                : #include <arpa/inet.h>
                                 29                 :                : 
                                 30                 :                : #include "common/string.h"
                                 31                 :                : #include "libpq/libpq.h"
                                 32                 :                : #include "miscadmin.h"
                                 33                 :                : #include "pgstat.h"
                                 34                 :                : #include "storage/fd.h"
                                 35                 :                : #include "storage/latch.h"
                                 36                 :                : #include "tcop/tcopprot.h"
                                 37                 :                : #include "utils/builtins.h"
                                 38                 :                : #include "utils/memutils.h"
                                 39                 :                : 
                                 40                 :                : /*
                                 41                 :                :  * These SSL-related #includes must come after all system-provided headers.
                                 42                 :                :  * This ensures that OpenSSL can take care of conflicts with Windows'
                                 43                 :                :  * <wincrypt.h> by #undef'ing the conflicting macros.  (We don't directly
                                 44                 :                :  * include <wincrypt.h>, but some other Windows headers do.)
                                 45                 :                :  */
                                 46                 :                : #include "common/openssl.h"
                                 47                 :                : #include <openssl/conf.h>
                                 48                 :                : #include <openssl/dh.h>
                                 49                 :                : #ifndef OPENSSL_NO_ECDH
                                 50                 :                : #include <openssl/ec.h>
                                 51                 :                : #endif
                                 52                 :                : #include <openssl/x509v3.h>
                                 53                 :                : 
                                 54                 :                : 
                                 55                 :                : /* default init hook can be overridden by a shared library */
                                 56                 :                : static void default_openssl_tls_init(SSL_CTX *context, bool isServerStart);
                                 57                 :                : openssl_tls_init_hook_typ openssl_tls_init_hook = default_openssl_tls_init;
                                 58                 :                : 
                                 59                 :                : static int  my_sock_read(BIO *h, char *buf, int size);
                                 60                 :                : static int  my_sock_write(BIO *h, const char *buf, int size);
                                 61                 :                : static BIO_METHOD *my_BIO_s_socket(void);
                                 62                 :                : static int  my_SSL_set_fd(Port *port, int fd);
                                 63                 :                : 
                                 64                 :                : static DH  *load_dh_file(char *filename, bool isServerStart);
                                 65                 :                : static DH  *load_dh_buffer(const char *buffer, size_t len);
                                 66                 :                : static int  ssl_external_passwd_cb(char *buf, int size, int rwflag, void *userdata);
                                 67                 :                : static int  dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata);
                                 68                 :                : static int  verify_cb(int ok, X509_STORE_CTX *ctx);
                                 69                 :                : static void info_cb(const SSL *ssl, int type, int args);
                                 70                 :                : static int  alpn_cb(SSL *ssl,
                                 71                 :                :                     const unsigned char **out,
                                 72                 :                :                     unsigned char *outlen,
                                 73                 :                :                     const unsigned char *in,
                                 74                 :                :                     unsigned int inlen,
                                 75                 :                :                     void *userdata);
                                 76                 :                : static bool initialize_dh(SSL_CTX *context, bool isServerStart);
                                 77                 :                : static bool initialize_ecdh(SSL_CTX *context, bool isServerStart);
                                 78                 :                : static const char *SSLerrmessage(unsigned long ecode);
                                 79                 :                : 
                                 80                 :                : static char *X509_NAME_to_cstring(X509_NAME *name);
                                 81                 :                : 
                                 82                 :                : static SSL_CTX *SSL_context = NULL;
                                 83                 :                : static bool SSL_initialized = false;
                                 84                 :                : static bool dummy_ssl_passwd_cb_called = false;
                                 85                 :                : static bool ssl_is_server_start;
                                 86                 :                : 
                                 87                 :                : static int  ssl_protocol_version_to_openssl(int v);
                                 88                 :                : static const char *ssl_protocol_version_to_string(int v);
                                 89                 :                : 
                                 90                 :                : /* for passing data back from verify_cb() */
                                 91                 :                : static const char *cert_errdetail;
                                 92                 :                : 
                                 93                 :                : /* ------------------------------------------------------------ */
                                 94                 :                : /*                       Public interface                       */
                                 95                 :                : /* ------------------------------------------------------------ */
                                 96                 :                : 
                                 97                 :                : int
 2657 tgl@sss.pgh.pa.us          98                 :CBC          28 : be_tls_init(bool isServerStart)
                                 99                 :                : {
                                100                 :                :     SSL_CTX    *context;
 1483 michael@paquier.xyz       101                 :             28 :     int         ssl_ver_min = -1;
                                102                 :             28 :     int         ssl_ver_max = -1;
                                103                 :                : 
                                104                 :                :     /* This stuff need be done only once. */
 2659 tgl@sss.pgh.pa.us         105         [ +  + ]:             28 :     if (!SSL_initialized)
                                106                 :                :     {
                                107                 :                : #ifdef HAVE_OPENSSL_INIT_SSL
 2768 heikki.linnakangas@i      108                 :             27 :         OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
                                109                 :                : #else
                                110                 :                :         OPENSSL_config(NULL);
                                111                 :                :         SSL_library_init();
                                112                 :                :         SSL_load_error_strings();
                                113                 :                : #endif
 2659 tgl@sss.pgh.pa.us         114                 :             27 :         SSL_initialized = true;
                                115                 :                :     }
                                116                 :                : 
                                117                 :                :     /*
                                118                 :                :      * Create a new SSL context into which we'll load all the configuration
                                119                 :                :      * settings.  If we fail partway through, we can avoid memory leakage by
                                120                 :                :      * freeing this context; we don't install it as active until the end.
                                121                 :                :      *
                                122                 :                :      * We use SSLv23_method() because it can negotiate use of the highest
                                123                 :                :      * mutually supported protocol version, while alternatives like
                                124                 :                :      * TLSv1_2_method() permit only one specific version.  Note that we don't
                                125                 :                :      * actually allow SSL v2 or v3, only TLS protocols (see below).
                                126                 :                :      */
                                127                 :             28 :     context = SSL_CTX_new(SSLv23_method());
                                128         [ -  + ]:             28 :     if (!context)
                                129                 :                :     {
 2657 tgl@sss.pgh.pa.us         130   [ #  #  #  # ]:UBC           0 :         ereport(isServerStart ? FATAL : LOG,
                                131                 :                :                 (errmsg("could not create SSL context: %s",
                                132                 :                :                         SSLerrmessage(ERR_get_error()))));
 2659                           133                 :              0 :         goto error;
                                134                 :                :     }
                                135                 :                : 
                                136                 :                :     /*
                                137                 :                :      * Disable OpenSSL's moving-write-buffer sanity check, because it causes
                                138                 :                :      * unnecessary failures in nonblocking send cases.
                                139                 :                :      */
 2659 tgl@sss.pgh.pa.us         140                 :CBC          28 :     SSL_CTX_set_mode(context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
                                141                 :                : 
                                142                 :                :     /*
                                143                 :                :      * Call init hook (usually to set password callback)
                                144                 :                :      */
 1431                           145                 :             28 :     (*openssl_tls_init_hook) (context, isServerStart);
                                146                 :                : 
                                147                 :                :     /* used by the callback */
 2239 peter_e@gmx.net           148                 :             28 :     ssl_is_server_start = isServerStart;
                                149                 :                : 
                                150                 :                :     /*
                                151                 :                :      * Load and verify server's certificate and private key
                                152                 :                :      */
 2659 tgl@sss.pgh.pa.us         153         [ -  + ]:             28 :     if (SSL_CTX_use_certificate_chain_file(context, ssl_cert_file) != 1)
                                154                 :                :     {
 2657 tgl@sss.pgh.pa.us         155   [ #  #  #  # ]:UBC           0 :         ereport(isServerStart ? FATAL : LOG,
                                156                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                157                 :                :                  errmsg("could not load server certificate file \"%s\": %s",
                                158                 :                :                         ssl_cert_file, SSLerrmessage(ERR_get_error()))));
 2659                           159                 :              0 :         goto error;
                                160                 :                :     }
                                161                 :                : 
 2277 peter_e@gmx.net           162         [ -  + ]:CBC          28 :     if (!check_ssl_key_file_permissions(ssl_key_file, isServerStart))
 2659 tgl@sss.pgh.pa.us         163                 :UBC           0 :         goto error;
                                164                 :                : 
                                165                 :                :     /*
                                166                 :                :      * OK, try to load the private key file.
                                167                 :                :      */
 2239 peter_e@gmx.net           168                 :CBC          28 :     dummy_ssl_passwd_cb_called = false;
                                169                 :                : 
 2659 tgl@sss.pgh.pa.us         170         [ +  + ]:             28 :     if (SSL_CTX_use_PrivateKey_file(context,
                                171                 :                :                                     ssl_key_file,
                                172                 :                :                                     SSL_FILETYPE_PEM) != 1)
                                173                 :                :     {
 2239 peter_e@gmx.net           174         [ -  + ]:              2 :         if (dummy_ssl_passwd_cb_called)
 2657 tgl@sss.pgh.pa.us         175   [ #  #  #  # ]:UBC           0 :             ereport(isServerStart ? FATAL : LOG,
                                176                 :                :                     (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                177                 :                :                      errmsg("private key file \"%s\" cannot be reloaded because it requires a passphrase",
                                178                 :                :                             ssl_key_file)));
                                179                 :                :         else
 2657 tgl@sss.pgh.pa.us         180   [ +  -  +  - ]:CBC           2 :             ereport(isServerStart ? FATAL : LOG,
                                181                 :                :                     (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                182                 :                :                      errmsg("could not load private key file \"%s\": %s",
                                183                 :                :                             ssl_key_file, SSLerrmessage(ERR_get_error()))));
 2659 tgl@sss.pgh.pa.us         184                 :UBC           0 :         goto error;
                                185                 :                :     }
                                186                 :                : 
 2659 tgl@sss.pgh.pa.us         187         [ -  + ]:CBC          26 :     if (SSL_CTX_check_private_key(context) != 1)
                                188                 :                :     {
 2657 tgl@sss.pgh.pa.us         189   [ #  #  #  # ]:UBC           0 :         ereport(isServerStart ? FATAL : LOG,
                                190                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                191                 :                :                  errmsg("check of private key failed: %s",
                                192                 :                :                         SSLerrmessage(ERR_get_error()))));
 2659                           193                 :              0 :         goto error;
                                194                 :                :     }
                                195                 :                : 
 1972 peter_e@gmx.net           196         [ +  - ]:CBC          26 :     if (ssl_min_protocol_version)
                                197                 :                :     {
 1483 michael@paquier.xyz       198                 :             26 :         ssl_ver_min = ssl_protocol_version_to_openssl(ssl_min_protocol_version);
                                199                 :                : 
                                200         [ -  + ]:             26 :         if (ssl_ver_min == -1)
                                201                 :                :         {
 1483 michael@paquier.xyz       202   [ #  #  #  # ]:UBC           0 :             ereport(isServerStart ? FATAL : LOG,
                                203                 :                :             /*- translator: first %s is a GUC option name, second %s is its value */
                                204                 :                :                     (errmsg("%s setting \"%s\" not supported by this build",
                                205                 :                :                             "ssl_min_protocol_version",
                                206                 :                :                             GetConfigOption("ssl_min_protocol_version",
                                207                 :                :                                             false, false))));
 1892 peter@eisentraut.org      208                 :              0 :             goto error;
                                209                 :                :         }
                                210                 :                : 
 1483 michael@paquier.xyz       211         [ -  + ]:CBC          26 :         if (!SSL_CTX_set_min_proto_version(context, ssl_ver_min))
                                212                 :                :         {
 1660 peter@eisentraut.org      213   [ #  #  #  # ]:UBC           0 :             ereport(isServerStart ? FATAL : LOG,
                                214                 :                :                     (errmsg("could not set minimum SSL protocol version")));
                                215                 :              0 :             goto error;
                                216                 :                :         }
                                217                 :                :     }
                                218                 :                : 
 1972 peter_e@gmx.net           219         [ +  + ]:CBC          26 :     if (ssl_max_protocol_version)
                                220                 :                :     {
 1483 michael@paquier.xyz       221                 :              1 :         ssl_ver_max = ssl_protocol_version_to_openssl(ssl_max_protocol_version);
                                222                 :                : 
                                223         [ -  + ]:              1 :         if (ssl_ver_max == -1)
                                224                 :                :         {
 1483 michael@paquier.xyz       225   [ #  #  #  # ]:UBC           0 :             ereport(isServerStart ? FATAL : LOG,
                                226                 :                :             /*- translator: first %s is a GUC option name, second %s is its value */
                                227                 :                :                     (errmsg("%s setting \"%s\" not supported by this build",
                                228                 :                :                             "ssl_max_protocol_version",
                                229                 :                :                             GetConfigOption("ssl_max_protocol_version",
                                230                 :                :                                             false, false))));
 1892 peter@eisentraut.org      231                 :              0 :             goto error;
                                232                 :                :         }
                                233                 :                : 
 1483 michael@paquier.xyz       234         [ -  + ]:CBC           1 :         if (!SSL_CTX_set_max_proto_version(context, ssl_ver_max))
                                235                 :                :         {
 1660 peter@eisentraut.org      236   [ #  #  #  # ]:UBC           0 :             ereport(isServerStart ? FATAL : LOG,
                                237                 :                :                     (errmsg("could not set maximum SSL protocol version")));
                                238                 :              0 :             goto error;
                                239                 :                :         }
                                240                 :                :     }
                                241                 :                : 
                                242                 :                :     /* Check compatibility of min/max protocols */
 1483 michael@paquier.xyz       243   [ +  -  +  + ]:CBC          26 :     if (ssl_min_protocol_version &&
                                244                 :                :         ssl_max_protocol_version)
                                245                 :                :     {
                                246                 :                :         /*
                                247                 :                :          * No need to check for invalid values (-1) for each protocol number
                                248                 :                :          * as the code above would have already generated an error.
                                249                 :                :          */
                                250         [ +  - ]:              1 :         if (ssl_ver_min > ssl_ver_max)
                                251                 :                :         {
                                252   [ +  -  +  - ]:              1 :             ereport(isServerStart ? FATAL : LOG,
                                253                 :                :                     (errmsg("could not set SSL protocol version range"),
                                254                 :                :                      errdetail("%s cannot be higher than %s",
                                255                 :                :                                "ssl_min_protocol_version",
                                256                 :                :                                "ssl_max_protocol_version")));
 1445 michael@paquier.xyz       257                 :UBC           0 :             goto error;
                                258                 :                :         }
                                259                 :                :     }
                                260                 :                : 
                                261                 :                :     /* disallow SSL session tickets */
 2445 tgl@sss.pgh.pa.us         262                 :CBC          25 :     SSL_CTX_set_options(context, SSL_OP_NO_TICKET);
                                263                 :                : 
                                264                 :                :     /* disallow SSL session caching, too */
                                265                 :             25 :     SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF);
                                266                 :                : 
                                267                 :                :     /* disallow SSL compression */
 1132 michael@paquier.xyz       268                 :             25 :     SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
                                269                 :                : 
                                270                 :                : #ifdef SSL_OP_NO_RENEGOTIATION
                                271                 :                : 
                                272                 :                :     /*
                                273                 :                :      * Disallow SSL renegotiation, option available since 1.1.0h.  This
                                274                 :                :      * concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no
                                275                 :                :      * support for renegotiation.
                                276                 :                :      */
 1055                           277                 :             25 :     SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
                                278                 :                : #endif
                                279                 :                : 
                                280                 :                :     /* set up ephemeral DH and ECDH keys */
 2449 heikki.linnakangas@i      281         [ -  + ]:             25 :     if (!initialize_dh(context, isServerStart))
 2449 heikki.linnakangas@i      282                 :UBC           0 :         goto error;
 2657 tgl@sss.pgh.pa.us         283         [ -  + ]:CBC          25 :     if (!initialize_ecdh(context, isServerStart))
 2659 tgl@sss.pgh.pa.us         284                 :UBC           0 :         goto error;
                                285                 :                : 
                                286                 :                :     /* set up the allowed cipher list */
 2659 tgl@sss.pgh.pa.us         287         [ -  + ]:CBC          25 :     if (SSL_CTX_set_cipher_list(context, SSLCipherSuites) != 1)
                                288                 :                :     {
 2657 tgl@sss.pgh.pa.us         289   [ #  #  #  # ]:UBC           0 :         ereport(isServerStart ? FATAL : LOG,
                                290                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                291                 :                :                  errmsg("could not set the cipher list (no valid ciphers available)")));
 2659                           292                 :              0 :         goto error;
                                293                 :                :     }
                                294                 :                : 
                                295                 :                :     /* Let server choose order */
 3527 heikki.linnakangas@i      296         [ +  - ]:CBC          25 :     if (SSLPreferServerCiphers)
 2659 tgl@sss.pgh.pa.us         297                 :             25 :         SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE);
                                298                 :                : 
                                299                 :                :     /*
                                300                 :                :      * Load CA store, so we can verify client certificates if needed.
                                301                 :                :      */
 3527 heikki.linnakangas@i      302         [ +  + ]:             25 :     if (ssl_ca_file[0])
                                303                 :                :     {
                                304                 :                :         STACK_OF(X509_NAME) * root_cert_list;
                                305                 :                : 
 2659 tgl@sss.pgh.pa.us         306   [ +  -  -  + ]:             42 :         if (SSL_CTX_load_verify_locations(context, ssl_ca_file, NULL) != 1 ||
 3527 heikki.linnakangas@i      307                 :             21 :             (root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL)
                                308                 :                :         {
 2657 tgl@sss.pgh.pa.us         309   [ #  #  #  # ]:UBC           0 :             ereport(isServerStart ? FATAL : LOG,
                                310                 :                :                     (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                311                 :                :                      errmsg("could not load root certificate file \"%s\": %s",
                                312                 :                :                             ssl_ca_file, SSLerrmessage(ERR_get_error()))));
 2659                           313                 :              0 :             goto error;
                                314                 :                :         }
                                315                 :                : 
                                316                 :                :         /*
                                317                 :                :          * Tell OpenSSL to send the list of root certs we trust to clients in
                                318                 :                :          * CertificateRequests.  This lets a client with a keystore select the
                                319                 :                :          * appropriate client certificate to send to us.  Also, this ensures
                                320                 :                :          * that the SSL context will "own" the root_cert_list and remember to
                                321                 :                :          * free it when no longer needed.
                                322                 :                :          */
 1125 tgl@sss.pgh.pa.us         323                 :CBC          21 :         SSL_CTX_set_client_CA_list(context, root_cert_list);
                                324                 :                : 
                                325                 :                :         /*
                                326                 :                :          * Always ask for SSL client cert, but don't fail if it's not
                                327                 :                :          * presented.  We might fail such connections later, depending on what
                                328                 :                :          * we find in pg_hba.conf.
                                329                 :                :          */
                                330                 :             21 :         SSL_CTX_set_verify(context,
                                331                 :                :                            (SSL_VERIFY_PEER |
                                332                 :                :                             SSL_VERIFY_CLIENT_ONCE),
                                333                 :                :                            verify_cb);
                                334                 :                :     }
                                335                 :                : 
                                336                 :                :     /*----------
                                337                 :                :      * Load the Certificate Revocation List (CRL).
                                338                 :                :      * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html
                                339                 :                :      *----------
                                340                 :                :      */
 1151 peter@eisentraut.org      341   [ +  +  -  + ]:             25 :     if (ssl_crl_file[0] || ssl_crl_dir[0])
                                342                 :                :     {
 2659 tgl@sss.pgh.pa.us         343                 :             21 :         X509_STORE *cvstore = SSL_CTX_get_cert_store(context);
                                344                 :                : 
 3527 heikki.linnakangas@i      345         [ +  - ]:             21 :         if (cvstore)
                                346                 :                :         {
                                347                 :                :             /* Set the flags to check against the complete CRL chain */
 1151 peter@eisentraut.org      348         [ +  - ]:             42 :             if (X509_STORE_load_locations(cvstore,
                                349         [ +  - ]:             21 :                                           ssl_crl_file[0] ? ssl_crl_file : NULL,
 1125 tgl@sss.pgh.pa.us         350         [ +  + ]:             21 :                                           ssl_crl_dir[0] ? ssl_crl_dir : NULL)
                                351                 :                :                 == 1)
                                352                 :                :             {
 3527 heikki.linnakangas@i      353                 :             21 :                 X509_STORE_set_flags(cvstore,
                                354                 :                :                                      X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
                                355                 :                :             }
 1151 peter@eisentraut.org      356         [ #  # ]:UBC           0 :             else if (ssl_crl_dir[0] == 0)
                                357                 :                :             {
 2657 tgl@sss.pgh.pa.us         358   [ #  #  #  # ]:              0 :                 ereport(isServerStart ? FATAL : LOG,
                                359                 :                :                         (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                360                 :                :                          errmsg("could not load SSL certificate revocation list file \"%s\": %s",
                                361                 :                :                                 ssl_crl_file, SSLerrmessage(ERR_get_error()))));
 2659                           362                 :              0 :                 goto error;
                                363                 :                :             }
 1151 peter@eisentraut.org      364         [ #  # ]:              0 :             else if (ssl_crl_file[0] == 0)
                                365                 :                :             {
                                366   [ #  #  #  # ]:              0 :                 ereport(isServerStart ? FATAL : LOG,
                                367                 :                :                         (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                368                 :                :                          errmsg("could not load SSL certificate revocation list directory \"%s\": %s",
                                369                 :                :                                 ssl_crl_dir, SSLerrmessage(ERR_get_error()))));
                                370                 :              0 :                 goto error;
                                371                 :                :             }
                                372                 :                :             else
                                373                 :                :             {
                                374   [ #  #  #  # ]:              0 :                 ereport(isServerStart ? FATAL : LOG,
                                375                 :                :                         (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                376                 :                :                          errmsg("could not load SSL certificate revocation list file \"%s\" or directory \"%s\": %s",
                                377                 :                :                                 ssl_crl_file, ssl_crl_dir,
                                378                 :                :                                 SSLerrmessage(ERR_get_error()))));
                                379                 :              0 :                 goto error;
                                380                 :                :             }
                                381                 :                :         }
                                382                 :                :     }
                                383                 :                : 
                                384                 :                :     /*
                                385                 :                :      * Success!  Replace any existing SSL_context.
                                386                 :                :      */
 2659 tgl@sss.pgh.pa.us         387         [ -  + ]:CBC          25 :     if (SSL_context)
 2659 tgl@sss.pgh.pa.us         388                 :UBC           0 :         SSL_CTX_free(SSL_context);
                                389                 :                : 
 2659 tgl@sss.pgh.pa.us         390                 :CBC          25 :     SSL_context = context;
                                391                 :                : 
                                392                 :                :     /*
                                393                 :                :      * Set flag to remember whether CA store has been loaded into SSL_context.
                                394                 :                :      */
                                395         [ +  + ]:             25 :     if (ssl_ca_file[0])
                                396                 :             21 :         ssl_loaded_verify_locations = true;
                                397                 :                :     else
                                398                 :              4 :         ssl_loaded_verify_locations = false;
                                399                 :                : 
                                400                 :             25 :     return 0;
                                401                 :                : 
                                402                 :                :     /* Clean up by releasing working context. */
 2659 tgl@sss.pgh.pa.us         403                 :UBC           0 : error:
                                404         [ #  # ]:              0 :     if (context)
                                405                 :              0 :         SSL_CTX_free(context);
                                406                 :              0 :     return -1;
                                407                 :                : }
                                408                 :                : 
                                409                 :                : void
 2659 tgl@sss.pgh.pa.us         410                 :CBC         125 : be_tls_destroy(void)
                                411                 :                : {
                                412         [ +  + ]:            125 :     if (SSL_context)
 2659 tgl@sss.pgh.pa.us         413                 :GBC           1 :         SSL_CTX_free(SSL_context);
 2659 tgl@sss.pgh.pa.us         414                 :CBC         125 :     SSL_context = NULL;
                                415                 :            125 :     ssl_loaded_verify_locations = false;
 3534 heikki.linnakangas@i      416                 :            125 : }
                                417                 :                : 
                                418                 :                : int
 3527                           419                 :            185 : be_tls_open_server(Port *port)
                                420                 :                : {
                                421                 :                :     int         r;
                                422                 :                :     int         err;
                                423                 :                :     int         waitfor;
                                424                 :                :     unsigned long ecode;
                                425                 :                :     bool        give_proto_hint;
                                426                 :                : 
                                427         [ -  + ]:            185 :     Assert(!port->ssl);
                                428         [ -  + ]:            185 :     Assert(!port->peer);
                                429                 :                : 
 2659 tgl@sss.pgh.pa.us         430         [ -  + ]:            185 :     if (!SSL_context)
                                431                 :                :     {
 2659 tgl@sss.pgh.pa.us         432         [ #  # ]:UBC           0 :         ereport(COMMERROR,
                                433                 :                :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                434                 :                :                  errmsg("could not initialize SSL connection: SSL context not set up")));
                                435                 :              0 :         return -1;
                                436                 :                :     }
                                437                 :                : 
                                438                 :                :     /* set up debugging/info callback */
 1178 michael@paquier.xyz       439                 :CBC         185 :     SSL_CTX_set_info_callback(SSL_context, info_cb);
                                440                 :                : 
                                441                 :                :     /* enable ALPN */
    6 heikki.linnakangas@i      442                 :GNC         185 :     SSL_CTX_set_alpn_select_cb(SSL_context, alpn_cb, port);
                                443                 :                : 
 3527 heikki.linnakangas@i      444         [ -  + ]:CBC         185 :     if (!(port->ssl = SSL_new(SSL_context)))
                                445                 :                :     {
 3527 heikki.linnakangas@i      446         [ #  # ]:UBC           0 :         ereport(COMMERROR,
                                447                 :                :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                448                 :                :                  errmsg("could not initialize SSL connection: %s",
                                449                 :                :                         SSLerrmessage(ERR_get_error()))));
                                450                 :              0 :         return -1;
                                451                 :                :     }
 3527 heikki.linnakangas@i      452         [ -  + ]:CBC         185 :     if (!my_SSL_set_fd(port, port->sock))
                                453                 :                :     {
 3527 heikki.linnakangas@i      454         [ #  # ]:UBC           0 :         ereport(COMMERROR,
                                455                 :                :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                456                 :                :                  errmsg("could not set SSL socket: %s",
                                457                 :                :                         SSLerrmessage(ERR_get_error()))));
                                458                 :              0 :         return -1;
                                459                 :                :     }
 3527 heikki.linnakangas@i      460                 :CBC         185 :     port->ssl_in_use = true;
                                461                 :                : 
                                462                 :            653 : aloop:
                                463                 :                : 
                                464                 :                :     /*
                                465                 :                :      * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
                                466                 :                :      * queue.  In general, the current thread's error queue must be empty
                                467                 :                :      * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
                                468                 :                :      * not work reliably.  An extension may have failed to clear the
                                469                 :                :      * per-thread error queue following another call to an OpenSSL I/O
                                470                 :                :      * routine.
                                471                 :                :      */
  125 tgl@sss.pgh.pa.us         472                 :            653 :     errno = 0;
 2928 peter_e@gmx.net           473                 :            653 :     ERR_clear_error();
 3527 heikki.linnakangas@i      474                 :            653 :     r = SSL_accept(port->ssl);
                                475         [ +  + ]:            653 :     if (r <= 0)
                                476                 :                :     {
                                477                 :            486 :         err = SSL_get_error(port->ssl, r);
                                478                 :                : 
                                479                 :                :         /*
                                480                 :                :          * Other clients of OpenSSL in the backend may fail to call
                                481                 :                :          * ERR_get_error(), but we always do, so as to not cause problems for
                                482                 :                :          * OpenSSL clients that don't call ERR_clear_error() defensively.  Be
                                483                 :                :          * sure that this happens by calling now. SSL_get_error() relies on
                                484                 :                :          * the OpenSSL per-thread error queue being intact, so this is the
                                485                 :                :          * earliest possible point ERR_get_error() may be called.
                                486                 :                :          */
 2928 peter_e@gmx.net           487                 :            486 :         ecode = ERR_get_error();
 3527 heikki.linnakangas@i      488   [ +  +  +  -  :            486 :         switch (err)
                                                 - ]
                                489                 :                :         {
                                490                 :            468 :             case SSL_ERROR_WANT_READ:
                                491                 :                :             case SSL_ERROR_WANT_WRITE:
                                492                 :                :                 /* not allowed during connection establishment */
 3358 andres@anarazel.de        493         [ -  + ]:            468 :                 Assert(!port->noblock);
                                494                 :                : 
                                495                 :                :                 /*
                                496                 :                :                  * No need to care about timeouts/interrupts here. At this
                                497                 :                :                  * point authentication_timeout still employs
                                498                 :                :                  * StartupPacketTimeoutHandler() which directly exits.
                                499                 :                :                  */
                                500         [ +  - ]:            468 :                 if (err == SSL_ERROR_WANT_READ)
 1967 tmunro@postgresql.or      501                 :            468 :                     waitfor = WL_SOCKET_READABLE | WL_EXIT_ON_PM_DEATH;
                                502                 :                :                 else
 1967 tmunro@postgresql.or      503                 :UBC           0 :                     waitfor = WL_SOCKET_WRITEABLE | WL_EXIT_ON_PM_DEATH;
                                504                 :                : 
 1969 tmunro@postgresql.or      505                 :CBC         468 :                 (void) WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0,
                                506                 :                :                                          WAIT_EVENT_SSL_OPEN_SERVER);
 3527 heikki.linnakangas@i      507                 :            468 :                 goto aloop;
                                508                 :              4 :             case SSL_ERROR_SYSCALL:
  125 tgl@sss.pgh.pa.us         509   [ +  -  -  + ]:              4 :                 if (r < 0 && errno != 0)
 3527 heikki.linnakangas@i      510         [ #  # ]:UBC           0 :                     ereport(COMMERROR,
                                511                 :                :                             (errcode_for_socket_access(),
                                512                 :                :                              errmsg("could not accept SSL connection: %m")));
                                513                 :                :                 else
 3527 heikki.linnakangas@i      514         [ +  - ]:CBC           4 :                     ereport(COMMERROR,
                                515                 :                :                             (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                516                 :                :                              errmsg("could not accept SSL connection: EOF detected")));
                                517                 :              4 :                 break;
                                518                 :             14 :             case SSL_ERROR_SSL:
 1387 tgl@sss.pgh.pa.us         519                 :             14 :                 switch (ERR_GET_REASON(ecode))
                                520                 :                :                 {
                                521                 :                :                         /*
                                522                 :                :                          * UNSUPPORTED_PROTOCOL, WRONG_VERSION_NUMBER, and
                                523                 :                :                          * TLSV1_ALERT_PROTOCOL_VERSION have been observed
                                524                 :                :                          * when trying to communicate with an old OpenSSL
                                525                 :                :                          * library, or when the client and server specify
                                526                 :                :                          * disjoint protocol ranges.  NO_PROTOCOLS_AVAILABLE
                                527                 :                :                          * occurs if there's a local misconfiguration (which
                                528                 :                :                          * can happen despite our checks, if openssl.cnf
                                529                 :                :                          * injects a limit we didn't account for).  It's not
                                530                 :                :                          * very clear what would make OpenSSL return the other
                                531                 :                :                          * codes listed here, but a hint about protocol
                                532                 :                :                          * versions seems like it's appropriate for all.
                                533                 :                :                          */
 1387 tgl@sss.pgh.pa.us         534                 :UBC           0 :                     case SSL_R_NO_PROTOCOLS_AVAILABLE:
                                535                 :                :                     case SSL_R_UNSUPPORTED_PROTOCOL:
                                536                 :                :                     case SSL_R_BAD_PROTOCOL_VERSION_NUMBER:
                                537                 :                :                     case SSL_R_UNKNOWN_PROTOCOL:
                                538                 :                :                     case SSL_R_UNKNOWN_SSL_VERSION:
                                539                 :                :                     case SSL_R_UNSUPPORTED_SSL_VERSION:
                                540                 :                :                     case SSL_R_WRONG_SSL_VERSION:
                                541                 :                :                     case SSL_R_WRONG_VERSION_NUMBER:
                                542                 :                :                     case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
                                543                 :                : #ifdef SSL_R_VERSION_TOO_HIGH
                                544                 :                :                     case SSL_R_VERSION_TOO_HIGH:
                                545                 :                :                     case SSL_R_VERSION_TOO_LOW:
                                546                 :                : #endif
                                547                 :              0 :                         give_proto_hint = true;
                                548                 :              0 :                         break;
 1387 tgl@sss.pgh.pa.us         549                 :CBC          14 :                     default:
                                550                 :             14 :                         give_proto_hint = false;
                                551                 :             14 :                         break;
                                552                 :                :                 }
 3527 heikki.linnakangas@i      553   [ +  -  +  +  :             14 :                 ereport(COMMERROR,
                                     -  +  -  -  -  
                                                 - ]
                                554                 :                :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                555                 :                :                          errmsg("could not accept SSL connection: %s",
                                556                 :                :                                 SSLerrmessage(ecode)),
                                557                 :                :                          cert_errdetail ? errdetail_internal("%s", cert_errdetail) : 0,
                                558                 :                :                          give_proto_hint ?
                                559                 :                :                          errhint("This may indicate that the client does not support any SSL protocol version between %s and %s.",
                                560                 :                :                                  ssl_min_protocol_version ?
                                561                 :                :                                  ssl_protocol_version_to_string(ssl_min_protocol_version) :
                                562                 :                :                                  MIN_OPENSSL_TLS_VERSION,
                                563                 :                :                                  ssl_max_protocol_version ?
                                564                 :                :                                  ssl_protocol_version_to_string(ssl_max_protocol_version) :
                                565                 :                :                                  MAX_OPENSSL_TLS_VERSION) : 0));
  639 peter@eisentraut.org      566                 :             14 :                 cert_errdetail = NULL;
 3527 heikki.linnakangas@i      567                 :             14 :                 break;
 3527 heikki.linnakangas@i      568                 :UBC           0 :             case SSL_ERROR_ZERO_RETURN:
                                569         [ #  # ]:              0 :                 ereport(COMMERROR,
                                570                 :                :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                571                 :                :                          errmsg("could not accept SSL connection: EOF detected")));
                                572                 :              0 :                 break;
                                573                 :              0 :             default:
                                574         [ #  # ]:              0 :                 ereport(COMMERROR,
                                575                 :                :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                576                 :                :                          errmsg("unrecognized SSL error code: %d",
                                577                 :                :                                 err)));
                                578                 :              0 :                 break;
                                579                 :                :         }
 3527 heikki.linnakangas@i      580                 :CBC          18 :         return -1;
                                581                 :                :     }
                                582                 :                : 
                                583                 :                :     /* Get the protocol selected by ALPN */
    6 heikki.linnakangas@i      584                 :GNC         167 :     port->alpn_used = false;
                                585                 :                :     {
                                586                 :                :         const unsigned char *selected;
                                587                 :                :         unsigned int len;
                                588                 :                : 
                                589                 :            167 :         SSL_get0_alpn_selected(port->ssl, &selected, &len);
                                590                 :                : 
                                591                 :                :         /* If ALPN is used, check that we negotiated the expected protocol */
                                592         [ +  - ]:            167 :         if (selected != NULL)
                                593                 :                :         {
                                594         [ +  - ]:            167 :             if (len == strlen(PG_ALPN_PROTOCOL) &&
                                595         [ +  - ]:            167 :                 memcmp(selected, PG_ALPN_PROTOCOL, strlen(PG_ALPN_PROTOCOL)) == 0)
                                596                 :                :             {
                                597                 :            167 :                 port->alpn_used = true;
                                598                 :                :             }
                                599                 :                :             else
                                600                 :                :             {
                                601                 :                :                 /* shouldn't happen */
    6 heikki.linnakangas@i      602         [ #  # ]:UNC           0 :                 ereport(COMMERROR,
                                603                 :                :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                604                 :                :                          errmsg("received SSL connection request with unexpected ALPN protocol")));
                                605                 :                :             }
                                606                 :                :         }
                                607                 :                :     }
                                608                 :                : 
                                609                 :                :     /* Get client certificate, if available. */
 3527 heikki.linnakangas@i      610                 :CBC         167 :     port->peer = SSL_get_peer_certificate(port->ssl);
                                611                 :                : 
                                612                 :                :     /* and extract the Common Name and Distinguished Name from it. */
                                613                 :            167 :     port->peer_cn = NULL;
 1112 andrew@dunslane.net       614                 :            167 :     port->peer_dn = NULL;
 3527 heikki.linnakangas@i      615                 :            167 :     port->peer_cert_valid = false;
                                616         [ +  + ]:            167 :     if (port->peer != NULL)
                                617                 :                :     {
                                618                 :                :         int         len;
 1112 andrew@dunslane.net       619                 :             29 :         X509_NAME  *x509name = X509_get_subject_name(port->peer);
                                620                 :                :         char       *peer_dn;
                                621                 :             29 :         BIO        *bio = NULL;
                                622                 :             29 :         BUF_MEM    *bio_buf = NULL;
                                623                 :                : 
                                624                 :             29 :         len = X509_NAME_get_text_by_NID(x509name, NID_commonName, NULL, 0);
 3527 heikki.linnakangas@i      625         [ +  - ]:             29 :         if (len != -1)
                                626                 :                :         {
                                627                 :                :             char       *peer_cn;
                                628                 :                : 
                                629                 :             29 :             peer_cn = MemoryContextAlloc(TopMemoryContext, len + 1);
 1112 andrew@dunslane.net       630                 :             29 :             r = X509_NAME_get_text_by_NID(x509name, NID_commonName, peer_cn,
                                631                 :                :                                           len + 1);
 3527 heikki.linnakangas@i      632                 :             29 :             peer_cn[len] = '\0';
                                633         [ -  + ]:             29 :             if (r != len)
                                634                 :                :             {
                                635                 :                :                 /* shouldn't happen */
 3527 heikki.linnakangas@i      636                 :UBC           0 :                 pfree(peer_cn);
                                637                 :              0 :                 return -1;
                                638                 :                :             }
                                639                 :                : 
                                640                 :                :             /*
                                641                 :                :              * Reject embedded NULLs in certificate common name to prevent
                                642                 :                :              * attacks like CVE-2009-4034.
                                643                 :                :              */
 3527 heikki.linnakangas@i      644         [ -  + ]:CBC          29 :             if (len != strlen(peer_cn))
                                645                 :                :             {
 3527 heikki.linnakangas@i      646         [ #  # ]:UBC           0 :                 ereport(COMMERROR,
                                647                 :                :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                648                 :                :                          errmsg("SSL certificate's common name contains embedded null")));
                                649                 :              0 :                 pfree(peer_cn);
                                650                 :              0 :                 return -1;
                                651                 :                :             }
                                652                 :                : 
 3527 heikki.linnakangas@i      653                 :CBC          29 :             port->peer_cn = peer_cn;
                                654                 :                :         }
                                655                 :                : 
 1112 andrew@dunslane.net       656                 :             29 :         bio = BIO_new(BIO_s_mem());
                                657         [ -  + ]:             29 :         if (!bio)
                                658                 :                :         {
  205 dgustafsson@postgres      659         [ #  # ]:UBC           0 :             if (port->peer_cn != NULL)
                                660                 :                :             {
                                661                 :              0 :                 pfree(port->peer_cn);
                                662                 :              0 :                 port->peer_cn = NULL;
                                663                 :                :             }
 1112 andrew@dunslane.net       664                 :              0 :             return -1;
                                665                 :                :         }
                                666                 :                : 
                                667                 :                :         /*
                                668                 :                :          * RFC2253 is the closest thing to an accepted standard format for
                                669                 :                :          * DNs. We have documented how to produce this format from a
                                670                 :                :          * certificate. It uses commas instead of slashes for delimiters,
                                671                 :                :          * which make regular expression matching a bit easier. Also note that
                                672                 :                :          * it prints the Subject fields in reverse order.
                                673                 :                :          */
  205 dgustafsson@postgres      674   [ +  -  -  + ]:CBC          58 :         if (X509_NAME_print_ex(bio, x509name, 0, XN_FLAG_RFC2253) == -1 ||
                                675                 :             29 :             BIO_get_mem_ptr(bio, &bio_buf) <= 0)
                                676                 :                :         {
 1112 andrew@dunslane.net       677                 :UBC           0 :             BIO_free(bio);
  205 dgustafsson@postgres      678         [ #  # ]:              0 :             if (port->peer_cn != NULL)
                                679                 :                :             {
                                680                 :              0 :                 pfree(port->peer_cn);
                                681                 :              0 :                 port->peer_cn = NULL;
                                682                 :                :             }
 1112 andrew@dunslane.net       683                 :              0 :             return -1;
                                684                 :                :         }
 1112 andrew@dunslane.net       685                 :CBC          29 :         peer_dn = MemoryContextAlloc(TopMemoryContext, bio_buf->length + 1);
                                686                 :             29 :         memcpy(peer_dn, bio_buf->data, bio_buf->length);
                                687                 :             29 :         len = bio_buf->length;
                                688                 :             29 :         BIO_free(bio);
                                689                 :             29 :         peer_dn[len] = '\0';
                                690         [ -  + ]:             29 :         if (len != strlen(peer_dn))
                                691                 :                :         {
 1112 andrew@dunslane.net       692         [ #  # ]:UBC           0 :             ereport(COMMERROR,
                                693                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                694                 :                :                      errmsg("SSL certificate's distinguished name contains embedded null")));
                                695                 :              0 :             pfree(peer_dn);
  205 dgustafsson@postgres      696         [ #  # ]:              0 :             if (port->peer_cn != NULL)
                                697                 :                :             {
                                698                 :              0 :                 pfree(port->peer_cn);
                                699                 :              0 :                 port->peer_cn = NULL;
                                700                 :                :             }
 1112 andrew@dunslane.net       701                 :              0 :             return -1;
                                702                 :                :         }
                                703                 :                : 
 1112 andrew@dunslane.net       704                 :CBC          29 :         port->peer_dn = peer_dn;
                                705                 :                : 
 3527 heikki.linnakangas@i      706                 :             29 :         port->peer_cert_valid = true;
                                707                 :                :     }
                                708                 :                : 
                                709                 :            167 :     return 0;
                                710                 :                : }
                                711                 :                : 
                                712                 :                : void
                                713                 :            185 : be_tls_close(Port *port)
                                714                 :                : {
                                715         [ +  - ]:            185 :     if (port->ssl)
                                716                 :                :     {
                                717                 :            185 :         SSL_shutdown(port->ssl);
                                718                 :            185 :         SSL_free(port->ssl);
                                719                 :            185 :         port->ssl = NULL;
                                720                 :            185 :         port->ssl_in_use = false;
                                721                 :                :     }
                                722                 :                : 
                                723         [ +  + ]:            185 :     if (port->peer)
                                724                 :                :     {
                                725                 :             29 :         X509_free(port->peer);
                                726                 :             29 :         port->peer = NULL;
                                727                 :                :     }
                                728                 :                : 
                                729         [ +  + ]:            185 :     if (port->peer_cn)
                                730                 :                :     {
                                731                 :             29 :         pfree(port->peer_cn);
                                732                 :             29 :         port->peer_cn = NULL;
                                733                 :                :     }
                                734                 :                : 
 1112 andrew@dunslane.net       735         [ +  + ]:            185 :     if (port->peer_dn)
                                736                 :                :     {
                                737                 :             29 :         pfree(port->peer_dn);
                                738                 :             29 :         port->peer_dn = NULL;
                                739                 :                :     }
 3534 heikki.linnakangas@i      740                 :            185 : }
                                741                 :                : 
                                742                 :                : ssize_t
 3348                           743                 :            782 : be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
                                744                 :                : {
                                745                 :                :     ssize_t     n;
                                746                 :                :     int         err;
                                747                 :                :     unsigned long ecode;
                                748                 :                : 
 3527                           749                 :            782 :     errno = 0;
 2928 peter_e@gmx.net           750                 :            782 :     ERR_clear_error();
 3527 heikki.linnakangas@i      751                 :            782 :     n = SSL_read(port->ssl, ptr, len);
                                752                 :            782 :     err = SSL_get_error(port->ssl, n);
 2928 peter_e@gmx.net           753   [ +  +  -  + ]:            782 :     ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
 3527 heikki.linnakangas@i      754   [ +  +  -  -  :            782 :     switch (err)
                                           -  +  - ]
                                755                 :                :     {
                                756                 :            416 :         case SSL_ERROR_NONE:
                                757                 :                :             /* a-ok */
 3534                           758                 :            416 :             break;
 3527                           759                 :            349 :         case SSL_ERROR_WANT_READ:
 3348                           760                 :            349 :             *waitfor = WL_SOCKET_READABLE;
                                761                 :            349 :             errno = EWOULDBLOCK;
                                762                 :            349 :             n = -1;
                                763                 :            349 :             break;
 3527 heikki.linnakangas@i      764                 :UBC           0 :         case SSL_ERROR_WANT_WRITE:
 3348                           765                 :              0 :             *waitfor = WL_SOCKET_WRITEABLE;
                                766                 :              0 :             errno = EWOULDBLOCK;
                                767                 :              0 :             n = -1;
                                768                 :              0 :             break;
 3527                           769                 :              0 :         case SSL_ERROR_SYSCALL:
                                770                 :                :             /* leave it to caller to ereport the value of errno */
  125 tgl@sss.pgh.pa.us         771   [ #  #  #  # ]:              0 :             if (n != -1 || errno == 0)
                                772                 :                :             {
 3527 heikki.linnakangas@i      773                 :              0 :                 errno = ECONNRESET;
                                774                 :              0 :                 n = -1;
                                775                 :                :             }
 3534                           776                 :              0 :             break;
 3527                           777                 :              0 :         case SSL_ERROR_SSL:
                                778         [ #  # ]:              0 :             ereport(COMMERROR,
                                779                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                780                 :                :                      errmsg("SSL error: %s", SSLerrmessage(ecode))));
                                781                 :              0 :             errno = ECONNRESET;
                                782                 :              0 :             n = -1;
 3534                           783                 :              0 :             break;
 2477 heikki.linnakangas@i      784                 :CBC          17 :         case SSL_ERROR_ZERO_RETURN:
                                785                 :                :             /* connection was cleanly shut down by peer */
                                786                 :             17 :             n = 0;
                                787                 :             17 :             break;
 3534 heikki.linnakangas@i      788                 :UBC           0 :         default:
 3527                           789         [ #  # ]:              0 :             ereport(COMMERROR,
                                790                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                791                 :                :                      errmsg("unrecognized SSL error code: %d",
                                792                 :                :                             err)));
                                793                 :              0 :             errno = ECONNRESET;
                                794                 :              0 :             n = -1;
 3534                           795                 :              0 :             break;
                                796                 :                :     }
                                797                 :                : 
 3527 heikki.linnakangas@i      798                 :CBC         782 :     return n;
                                799                 :                : }
                                800                 :                : 
                                801                 :                : ssize_t
 3348                           802                 :            292 : be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
                                803                 :                : {
                                804                 :                :     ssize_t     n;
                                805                 :                :     int         err;
                                806                 :                :     unsigned long ecode;
                                807                 :                : 
 3527                           808                 :            292 :     errno = 0;
 2928 peter_e@gmx.net           809                 :            292 :     ERR_clear_error();
 3527 heikki.linnakangas@i      810                 :            292 :     n = SSL_write(port->ssl, ptr, len);
                                811                 :            292 :     err = SSL_get_error(port->ssl, n);
 2928 peter_e@gmx.net           812   [ +  -  -  + ]:            292 :     ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
 3527 heikki.linnakangas@i      813   [ +  -  -  -  :            292 :     switch (err)
                                           -  -  - ]
                                814                 :                :     {
                                815                 :            292 :         case SSL_ERROR_NONE:
                                816                 :                :             /* a-ok */
                                817                 :            292 :             break;
 3527 heikki.linnakangas@i      818                 :UBC           0 :         case SSL_ERROR_WANT_READ:
 3348                           819                 :              0 :             *waitfor = WL_SOCKET_READABLE;
                                820                 :              0 :             errno = EWOULDBLOCK;
                                821                 :              0 :             n = -1;
                                822                 :              0 :             break;
 3527                           823                 :              0 :         case SSL_ERROR_WANT_WRITE:
 3348                           824                 :              0 :             *waitfor = WL_SOCKET_WRITEABLE;
                                825                 :              0 :             errno = EWOULDBLOCK;
                                826                 :              0 :             n = -1;
                                827                 :              0 :             break;
 3527                           828                 :              0 :         case SSL_ERROR_SYSCALL:
                                829                 :                : 
                                830                 :                :             /*
                                831                 :                :              * Leave it to caller to ereport the value of errno.  However, if
                                832                 :                :              * errno is still zero then assume it's a read EOF situation, and
                                833                 :                :              * report ECONNRESET.  (This seems possible because SSL_write can
                                834                 :                :              * also do reads.)
                                835                 :                :              */
  125 tgl@sss.pgh.pa.us         836   [ #  #  #  # ]:              0 :             if (n != -1 || errno == 0)
                                837                 :                :             {
 3527 heikki.linnakangas@i      838                 :              0 :                 errno = ECONNRESET;
                                839                 :              0 :                 n = -1;
                                840                 :                :             }
                                841                 :              0 :             break;
                                842                 :              0 :         case SSL_ERROR_SSL:
                                843         [ #  # ]:              0 :             ereport(COMMERROR,
                                844                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                845                 :                :                      errmsg("SSL error: %s", SSLerrmessage(ecode))));
 2477                           846                 :              0 :             errno = ECONNRESET;
                                847                 :              0 :             n = -1;
                                848                 :              0 :             break;
 3527                           849                 :              0 :         case SSL_ERROR_ZERO_RETURN:
                                850                 :                : 
                                851                 :                :             /*
                                852                 :                :              * the SSL connection was closed, leave it to the caller to
                                853                 :                :              * ereport it
                                854                 :                :              */
                                855                 :              0 :             errno = ECONNRESET;
                                856                 :              0 :             n = -1;
                                857                 :              0 :             break;
                                858                 :              0 :         default:
                                859         [ #  # ]:              0 :             ereport(COMMERROR,
                                860                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                861                 :                :                      errmsg("unrecognized SSL error code: %d",
                                862                 :                :                             err)));
                                863                 :              0 :             errno = ECONNRESET;
                                864                 :              0 :             n = -1;
                                865                 :              0 :             break;
                                866                 :                :     }
                                867                 :                : 
 3527 heikki.linnakangas@i      868                 :CBC         292 :     return n;
                                869                 :                : }
                                870                 :                : 
                                871                 :                : /* ------------------------------------------------------------ */
                                872                 :                : /*                      Internal functions                      */
                                873                 :                : /* ------------------------------------------------------------ */
                                874                 :                : 
                                875                 :                : /*
                                876                 :                :  * Private substitute BIO: this does the sending and receiving using send() and
                                877                 :                :  * recv() instead. This is so that we can enable and disable interrupts
                                878                 :                :  * just while calling recv(). We cannot have interrupts occurring while
                                879                 :                :  * the bulk of OpenSSL runs, because it uses malloc() and possibly other
                                880                 :                :  * non-reentrant libc facilities. We also need to call send() and recv()
                                881                 :                :  * directly so it gets passed through the socket/signals layer on Win32.
                                882                 :                :  *
                                883                 :                :  * These functions are closely modelled on the standard socket BIO in OpenSSL;
                                884                 :                :  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
                                885                 :                :  */
                                886                 :                : 
                                887                 :                : static BIO_METHOD *my_bio_methods = NULL;
                                888                 :                : 
                                889                 :                : static int
                                890                 :           3383 : my_sock_read(BIO *h, char *buf, int size)
                                891                 :                : {
                                892                 :           3383 :     int         res = 0;
                                893                 :                : 
                                894         [ +  - ]:           3383 :     if (buf != NULL)
                                895                 :                :     {
  138 tgl@sss.pgh.pa.us         896                 :           3383 :         res = secure_raw_read(((Port *) BIO_get_app_data(h)), buf, size);
 3527 heikki.linnakangas@i      897                 :           3383 :         BIO_clear_retry_flags(h);
                                898         [ +  + ]:           3383 :         if (res <= 0)
                                899                 :                :         {
                                900                 :                :             /* If we were interrupted, tell caller to retry */
 3358 andres@anarazel.de        901   [ +  -  +  +  :            821 :             if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
                                              -  + ]
                                902                 :                :             {
 3527 heikki.linnakangas@i      903                 :            817 :                 BIO_set_retry_read(h);
                                904                 :                :             }
                                905                 :                :         }
                                906                 :                :     }
                                907                 :                : 
                                908                 :           3383 :     return res;
                                909                 :                : }
                                910                 :                : 
                                911                 :                : static int
                                912                 :           1156 : my_sock_write(BIO *h, const char *buf, int size)
                                913                 :                : {
                                914                 :           1156 :     int         res = 0;
                                915                 :                : 
  138 tgl@sss.pgh.pa.us         916                 :           1156 :     res = secure_raw_write(((Port *) BIO_get_app_data(h)), buf, size);
 3527 heikki.linnakangas@i      917                 :           1156 :     BIO_clear_retry_flags(h);
                                918         [ +  + ]:           1156 :     if (res <= 0)
                                919                 :                :     {
                                920                 :                :         /* If we were interrupted, tell caller to retry */
 3358 andres@anarazel.de        921   [ +  -  +  -  :             11 :         if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
                                              -  + ]
                                922                 :                :         {
 3527 heikki.linnakangas@i      923                 :UBC           0 :             BIO_set_retry_write(h);
                                924                 :                :         }
                                925                 :                :     }
                                926                 :                : 
 3527 heikki.linnakangas@i      927                 :CBC        1156 :     return res;
                                928                 :                : }
                                929                 :                : 
                                930                 :                : static BIO_METHOD *
                                931                 :            185 : my_BIO_s_socket(void)
                                932                 :                : {
 2768                           933         [ +  - ]:            185 :     if (!my_bio_methods)
                                934                 :                :     {
                                935                 :            185 :         BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
                                936                 :                : #ifdef HAVE_BIO_METH_NEW
                                937                 :                :         int         my_bio_index;
                                938                 :                : 
                                939                 :            185 :         my_bio_index = BIO_get_new_index();
                                940         [ -  + ]:            185 :         if (my_bio_index == -1)
 2768 heikki.linnakangas@i      941                 :UBC           0 :             return NULL;
  971 dgustafsson@postgres      942                 :CBC         185 :         my_bio_index |= (BIO_TYPE_DESCRIPTOR | BIO_TYPE_SOURCE_SINK);
 2768 heikki.linnakangas@i      943                 :            185 :         my_bio_methods = BIO_meth_new(my_bio_index, "PostgreSQL backend socket");
                                944         [ -  + ]:            185 :         if (!my_bio_methods)
 2768 heikki.linnakangas@i      945                 :UBC           0 :             return NULL;
 2768 heikki.linnakangas@i      946   [ +  -  +  - ]:CBC         370 :         if (!BIO_meth_set_write(my_bio_methods, my_sock_write) ||
                                947         [ +  - ]:            370 :             !BIO_meth_set_read(my_bio_methods, my_sock_read) ||
                                948         [ +  - ]:            370 :             !BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) ||
                                949         [ +  - ]:            370 :             !BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) ||
                                950         [ +  - ]:            370 :             !BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) ||
                                951         [ +  - ]:            370 :             !BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) ||
 2489 tgl@sss.pgh.pa.us         952         [ -  + ]:            370 :             !BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) ||
 2768 heikki.linnakangas@i      953                 :            185 :             !BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom)))
                                954                 :                :         {
 2768 heikki.linnakangas@i      955                 :UBC           0 :             BIO_meth_free(my_bio_methods);
                                956                 :              0 :             my_bio_methods = NULL;
                                957                 :              0 :             return NULL;
                                958                 :                :         }
                                959                 :                : #else
                                960                 :                :         my_bio_methods = malloc(sizeof(BIO_METHOD));
                                961                 :                :         if (!my_bio_methods)
                                962                 :                :             return NULL;
                                963                 :                :         memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
                                964                 :                :         my_bio_methods->bread = my_sock_read;
                                965                 :                :         my_bio_methods->bwrite = my_sock_write;
                                966                 :                : #endif
                                967                 :                :     }
 2768 heikki.linnakangas@i      968                 :CBC         185 :     return my_bio_methods;
                                969                 :                : }
                                970                 :                : 
                                971                 :                : /* This should exactly match OpenSSL's SSL_set_fd except for using my BIO */
                                972                 :                : static int
 3527                           973                 :            185 : my_SSL_set_fd(Port *port, int fd)
                                974                 :                : {
                                975                 :            185 :     int         ret = 0;
                                976                 :                :     BIO        *bio;
                                977                 :                :     BIO_METHOD *bio_method;
                                978                 :                : 
 2768                           979                 :            185 :     bio_method = my_BIO_s_socket();
                                980         [ -  + ]:            185 :     if (bio_method == NULL)
                                981                 :                :     {
 2768 heikki.linnakangas@i      982                 :UBC           0 :         SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
                                983                 :              0 :         goto err;
                                984                 :                :     }
 2768 heikki.linnakangas@i      985                 :CBC         185 :     bio = BIO_new(bio_method);
                                986                 :                : 
 3527                           987         [ -  + ]:            185 :     if (bio == NULL)
                                988                 :                :     {
 3527 heikki.linnakangas@i      989                 :UBC           0 :         SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
                                990                 :              0 :         goto err;
                                991                 :                :     }
  138 tgl@sss.pgh.pa.us         992                 :CBC         185 :     BIO_set_app_data(bio, port);
                                993                 :                : 
 3527 heikki.linnakangas@i      994                 :            185 :     BIO_set_fd(bio, fd, BIO_NOCLOSE);
                                995                 :            185 :     SSL_set_bio(port->ssl, bio, bio);
                                996                 :            185 :     ret = 1;
                                997                 :            185 : err:
                                998                 :            185 :     return ret;
                                999                 :                : }
                               1000                 :                : 
                               1001                 :                : /*
                               1002                 :                :  *  Load precomputed DH parameters.
                               1003                 :                :  *
                               1004                 :                :  *  To prevent "downgrade" attacks, we perform a number of checks
                               1005                 :                :  *  to verify that the DBA-generated DH parameters file contains
                               1006                 :                :  *  what we expect it to contain.
                               1007                 :                :  */
                               1008                 :                : static DH  *
 2449 heikki.linnakangas@i     1009                 :UBC           0 : load_dh_file(char *filename, bool isServerStart)
                               1010                 :                : {
                               1011                 :                :     FILE       *fp;
 3527                          1012                 :              0 :     DH         *dh = NULL;
                               1013                 :                :     int         codes;
                               1014                 :                : 
                               1015                 :                :     /* attempt to open file.  It's not an error if it doesn't exist. */
 2449                          1016         [ #  # ]:              0 :     if ((fp = AllocateFile(filename, "r")) == NULL)
                               1017                 :                :     {
                               1018   [ #  #  #  # ]:              0 :         ereport(isServerStart ? FATAL : LOG,
                               1019                 :                :                 (errcode_for_file_access(),
                               1020                 :                :                  errmsg("could not open DH parameters file \"%s\": %m",
                               1021                 :                :                         filename)));
 3527                          1022                 :              0 :         return NULL;
                               1023                 :                :     }
                               1024                 :                : 
                               1025                 :              0 :     dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
 2449                          1026                 :              0 :     FreeFile(fp);
                               1027                 :                : 
                               1028         [ #  # ]:              0 :     if (dh == NULL)
                               1029                 :                :     {
                               1030   [ #  #  #  # ]:              0 :         ereport(isServerStart ? FATAL : LOG,
                               1031                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                               1032                 :                :                  errmsg("could not load DH parameters file: %s",
                               1033                 :                :                         SSLerrmessage(ERR_get_error()))));
                               1034                 :              0 :         return NULL;
                               1035                 :                :     }
                               1036                 :                : 
                               1037                 :                :     /* make sure the DH parameters are usable */
                               1038         [ #  # ]:              0 :     if (DH_check(dh, &codes) == 0)
                               1039                 :                :     {
                               1040   [ #  #  #  # ]:              0 :         ereport(isServerStart ? FATAL : LOG,
                               1041                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                               1042                 :                :                  errmsg("invalid DH parameters: %s",
                               1043                 :                :                         SSLerrmessage(ERR_get_error()))));
 1121 tgl@sss.pgh.pa.us        1044                 :              0 :         DH_free(dh);
 2449 heikki.linnakangas@i     1045                 :              0 :         return NULL;
                               1046                 :                :     }
                               1047         [ #  # ]:              0 :     if (codes & DH_CHECK_P_NOT_PRIME)
                               1048                 :                :     {
                               1049   [ #  #  #  # ]:              0 :         ereport(isServerStart ? FATAL : LOG,
                               1050                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                               1051                 :                :                  errmsg("invalid DH parameters: p is not prime")));
 1121 tgl@sss.pgh.pa.us        1052                 :              0 :         DH_free(dh);
 2449 heikki.linnakangas@i     1053                 :              0 :         return NULL;
                               1054                 :                :     }
                               1055         [ #  # ]:              0 :     if ((codes & DH_NOT_SUITABLE_GENERATOR) &&
                               1056         [ #  # ]:              0 :         (codes & DH_CHECK_P_NOT_SAFE_PRIME))
                               1057                 :                :     {
                               1058   [ #  #  #  # ]:              0 :         ereport(isServerStart ? FATAL : LOG,
                               1059                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                               1060                 :                :                  errmsg("invalid DH parameters: neither suitable generator or safe prime")));
 1121 tgl@sss.pgh.pa.us        1061                 :              0 :         DH_free(dh);
 2449 heikki.linnakangas@i     1062                 :              0 :         return NULL;
                               1063                 :                :     }
                               1064                 :                : 
 3527                          1065                 :              0 :     return dh;
                               1066                 :                : }
                               1067                 :                : 
                               1068                 :                : /*
                               1069                 :                :  *  Load hardcoded DH parameters.
                               1070                 :                :  *
                               1071                 :                :  *  If DH parameters cannot be loaded from a specified file, we can load
                               1072                 :                :  *  the hardcoded DH parameters supplied with the backend to prevent
                               1073                 :                :  *  problems.
                               1074                 :                :  */
                               1075                 :                : static DH  *
 3527 heikki.linnakangas@i     1076                 :CBC          25 : load_dh_buffer(const char *buffer, size_t len)
                               1077                 :                : {
                               1078                 :                :     BIO        *bio;
                               1079                 :             25 :     DH         *dh = NULL;
                               1080                 :                : 
 1902 peter@eisentraut.org     1081                 :             25 :     bio = BIO_new_mem_buf(unconstify(char *, buffer), len);
 3527 heikki.linnakangas@i     1082         [ -  + ]:             25 :     if (bio == NULL)
 3527 heikki.linnakangas@i     1083                 :UBC           0 :         return NULL;
 3527 heikki.linnakangas@i     1084                 :CBC          25 :     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
                               1085         [ -  + ]:             25 :     if (dh == NULL)
 3527 heikki.linnakangas@i     1086         [ #  # ]:UBC           0 :         ereport(DEBUG2,
                               1087                 :                :                 (errmsg_internal("DH load buffer: %s",
                               1088                 :                :                                  SSLerrmessage(ERR_get_error()))));
 3527 heikki.linnakangas@i     1089                 :CBC          25 :     BIO_free(bio);
                               1090                 :                : 
                               1091                 :             25 :     return dh;
                               1092                 :                : }
                               1093                 :                : 
                               1094                 :                : /*
                               1095                 :                :  *  Passphrase collection callback using ssl_passphrase_command
                               1096                 :                :  */
                               1097                 :                : static int
 2239 peter_e@gmx.net          1098                 :              4 : ssl_external_passwd_cb(char *buf, int size, int rwflag, void *userdata)
                               1099                 :                : {
                               1100                 :                :     /* same prompt as OpenSSL uses internally */
                               1101                 :              4 :     const char *prompt = "Enter PEM pass phrase:";
                               1102                 :                : 
                               1103         [ -  + ]:              4 :     Assert(rwflag == 0);
                               1104                 :                : 
                               1105                 :              4 :     return run_ssl_passphrase_command(prompt, ssl_is_server_start, buf, size);
                               1106                 :                : }
                               1107                 :                : 
                               1108                 :                : /*
                               1109                 :                :  * Dummy passphrase callback
                               1110                 :                :  *
                               1111                 :                :  * If OpenSSL is told to use a passphrase-protected server key, by default
                               1112                 :                :  * it will issue a prompt on /dev/tty and try to read a key from there.
                               1113                 :                :  * That's no good during a postmaster SIGHUP cycle, not to mention SSL context
                               1114                 :                :  * reload in an EXEC_BACKEND postmaster child.  So override it with this dummy
                               1115                 :                :  * function that just returns an empty passphrase, guaranteeing failure.
                               1116                 :                :  */
                               1117                 :                : static int
 2239 peter_e@gmx.net          1118                 :UBC           0 : dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
                               1119                 :                : {
                               1120                 :                :     /* Set flag to change the error message we'll report */
                               1121                 :              0 :     dummy_ssl_passwd_cb_called = true;
                               1122                 :                :     /* And return empty string */
 2658 tgl@sss.pgh.pa.us        1123         [ #  # ]:              0 :     Assert(size > 0);
                               1124                 :              0 :     buf[0] = '\0';
                               1125                 :              0 :     return 0;
                               1126                 :                : }
                               1127                 :                : 
                               1128                 :                : /*
                               1129                 :                :  * Examines the provided certificate name, and if it's too long to log or
                               1130                 :                :  * contains unprintable ASCII, escapes and truncates it. The return value is
                               1131                 :                :  * always a new palloc'd string. (The input string is still modified in place,
                               1132                 :                :  * for ease of implementation.)
                               1133                 :                :  */
                               1134                 :                : static char *
  579 peter@eisentraut.org     1135                 :CBC          10 : prepare_cert_name(char *name)
                               1136                 :                : {
  639                          1137                 :             10 :     size_t      namelen = strlen(name);
  579                          1138                 :             10 :     char       *truncated = name;
                               1139                 :                : 
                               1140                 :                :     /*
                               1141                 :                :      * Common Names are 64 chars max, so for a common case where the CN is the
                               1142                 :                :      * last field, we can still print the longest possible CN with a
                               1143                 :                :      * 7-character prefix (".../CN=[64 chars]"), for a reasonable limit of 71
                               1144                 :                :      * characters.
                               1145                 :                :      */
                               1146                 :                : #define MAXLEN 71
                               1147                 :                : 
                               1148         [ +  + ]:             10 :     if (namelen > MAXLEN)
                               1149                 :                :     {
                               1150                 :                :         /*
                               1151                 :                :          * Keep the end of the name, not the beginning, since the most
                               1152                 :                :          * specific field is likely to give users the most information.
                               1153                 :                :          */
                               1154                 :              1 :         truncated = name + namelen - MAXLEN;
                               1155                 :              1 :         truncated[0] = truncated[1] = truncated[2] = '.';
                               1156                 :              1 :         namelen = MAXLEN;
                               1157                 :                :     }
                               1158                 :                : 
                               1159                 :                : #undef MAXLEN
                               1160                 :                : 
                               1161                 :             10 :     return pg_clean_ascii(truncated, 0);
                               1162                 :                : }
                               1163                 :                : 
                               1164                 :                : /*
                               1165                 :                :  *  Certificate verification callback
                               1166                 :                :  *
                               1167                 :                :  *  This callback allows us to examine intermediate problems during
                               1168                 :                :  *  verification, for later logging.
                               1169                 :                :  *
                               1170                 :                :  *  This callback also allows us to override the default acceptance
                               1171                 :                :  *  criteria (e.g., accepting self-signed or expired certs), but
                               1172                 :                :  *  for now we accept the default checks.
                               1173                 :                :  */
                               1174                 :                : static int
 3527 heikki.linnakangas@i     1175                 :             92 : verify_cb(int ok, X509_STORE_CTX *ctx)
                               1176                 :                : {
                               1177                 :                :     int         depth;
                               1178                 :                :     int         errcode;
                               1179                 :                :     const char *errstring;
                               1180                 :                :     StringInfoData str;
                               1181                 :                :     X509       *cert;
                               1182                 :                : 
  639 peter@eisentraut.org     1183         [ +  + ]:             92 :     if (ok)
                               1184                 :                :     {
                               1185                 :                :         /* Nothing to do for the successful case. */
                               1186                 :             87 :         return ok;
                               1187                 :                :     }
                               1188                 :                : 
                               1189                 :                :     /* Pull all the information we have on the verification failure. */
                               1190                 :              5 :     depth = X509_STORE_CTX_get_error_depth(ctx);
                               1191                 :              5 :     errcode = X509_STORE_CTX_get_error(ctx);
                               1192                 :              5 :     errstring = X509_verify_cert_error_string(errcode);
                               1193                 :                : 
                               1194                 :              5 :     initStringInfo(&str);
                               1195                 :              5 :     appendStringInfo(&str,
                               1196                 :              5 :                      _("Client certificate verification failed at depth %d: %s."),
                               1197                 :                :                      depth, errstring);
                               1198                 :                : 
                               1199                 :              5 :     cert = X509_STORE_CTX_get_current_cert(ctx);
                               1200         [ +  - ]:              5 :     if (cert)
                               1201                 :                :     {
                               1202                 :                :         char       *subject,
                               1203                 :                :                    *issuer;
                               1204                 :                :         char       *sub_prepared,
                               1205                 :                :                    *iss_prepared;
                               1206                 :                :         char       *serialno;
                               1207                 :                :         ASN1_INTEGER *sn;
                               1208                 :                :         BIGNUM     *b;
                               1209                 :                : 
                               1210                 :                :         /*
                               1211                 :                :          * Get the Subject and Issuer for logging, but don't let maliciously
                               1212                 :                :          * huge certs flood the logs, and don't reflect non-ASCII bytes into
                               1213                 :                :          * it either.
                               1214                 :                :          */
                               1215                 :              5 :         subject = X509_NAME_to_cstring(X509_get_subject_name(cert));
  579                          1216                 :              5 :         sub_prepared = prepare_cert_name(subject);
                               1217                 :              5 :         pfree(subject);
                               1218                 :                : 
  639                          1219                 :              5 :         issuer = X509_NAME_to_cstring(X509_get_issuer_name(cert));
  579                          1220                 :              5 :         iss_prepared = prepare_cert_name(issuer);
                               1221                 :              5 :         pfree(issuer);
                               1222                 :                : 
                               1223                 :                :         /*
                               1224                 :                :          * Pull the serial number, too, in case a Subject is still ambiguous.
                               1225                 :                :          * This mirrors be_tls_get_peer_serial().
                               1226                 :                :          */
  639                          1227                 :              5 :         sn = X509_get_serialNumber(cert);
                               1228                 :              5 :         b = ASN1_INTEGER_to_BN(sn, NULL);
                               1229                 :              5 :         serialno = BN_bn2dec(b);
                               1230                 :                : 
                               1231                 :              5 :         appendStringInfoChar(&str, '\n');
                               1232         [ -  + ]:              5 :         appendStringInfo(&str,
                               1233                 :              5 :                          _("Failed certificate data (unverified): subject \"%s\", serial number %s, issuer \"%s\"."),
  579 peter@eisentraut.org     1234                 :UBC           0 :                          sub_prepared, serialno ? serialno : _("unknown"),
                               1235                 :                :                          iss_prepared);
                               1236                 :                : 
  639 peter@eisentraut.org     1237                 :CBC           5 :         BN_free(b);
                               1238                 :              5 :         OPENSSL_free(serialno);
  579                          1239                 :              5 :         pfree(iss_prepared);
                               1240                 :              5 :         pfree(sub_prepared);
                               1241                 :                :     }
                               1242                 :                : 
                               1243                 :                :     /* Store our detail message to be logged later. */
  639                          1244                 :              5 :     cert_errdetail = str.data;
                               1245                 :                : 
 3527 heikki.linnakangas@i     1246                 :              5 :     return ok;
                               1247                 :                : }
                               1248                 :                : 
                               1249                 :                : /*
                               1250                 :                :  *  This callback is used to copy SSL information messages
                               1251                 :                :  *  into the PostgreSQL log.
                               1252                 :                :  */
                               1253                 :                : static void
                               1254                 :           4629 : info_cb(const SSL *ssl, int type, int args)
                               1255                 :                : {
                               1256                 :                :     const char *desc;
                               1257                 :                : 
 1178 michael@paquier.xyz      1258                 :           4629 :     desc = SSL_state_string_long(ssl);
                               1259                 :                : 
 3527 heikki.linnakangas@i     1260   [ +  +  +  +  :           4629 :     switch (type)
                                        -  -  +  +  
                                                 - ]
                               1261                 :                :     {
                               1262                 :            185 :         case SSL_CB_HANDSHAKE_START:
                               1263         [ -  + ]:            185 :             ereport(DEBUG4,
                               1264                 :                :                     (errmsg_internal("SSL: handshake start: \"%s\"", desc)));
 3534                          1265                 :            185 :             break;
 3527                          1266                 :            167 :         case SSL_CB_HANDSHAKE_DONE:
                               1267         [ -  + ]:            167 :             ereport(DEBUG4,
                               1268                 :                :                     (errmsg_internal("SSL: handshake done: \"%s\"", desc)));
 3534                          1269                 :            167 :             break;
 3527                          1270                 :           3434 :         case SSL_CB_ACCEPT_LOOP:
                               1271         [ -  + ]:           3434 :             ereport(DEBUG4,
                               1272                 :                :                     (errmsg_internal("SSL: accept loop: \"%s\"", desc)));
 3534                          1273                 :           3434 :             break;
 3527                          1274                 :            653 :         case SSL_CB_ACCEPT_EXIT:
                               1275         [ -  + ]:            653 :             ereport(DEBUG4,
                               1276                 :                :                     (errmsg_internal("SSL: accept exit (%d): \"%s\"", args, desc)));
                               1277                 :            653 :             break;
 3527 heikki.linnakangas@i     1278                 :UBC           0 :         case SSL_CB_CONNECT_LOOP:
                               1279         [ #  # ]:              0 :             ereport(DEBUG4,
                               1280                 :                :                     (errmsg_internal("SSL: connect loop: \"%s\"", desc)));
                               1281                 :              0 :             break;
                               1282                 :              0 :         case SSL_CB_CONNECT_EXIT:
                               1283         [ #  # ]:              0 :             ereport(DEBUG4,
                               1284                 :                :                     (errmsg_internal("SSL: connect exit (%d): \"%s\"", args, desc)));
                               1285                 :              0 :             break;
 3527 heikki.linnakangas@i     1286                 :CBC          26 :         case SSL_CB_READ_ALERT:
                               1287         [ -  + ]:             26 :             ereport(DEBUG4,
                               1288                 :                :                     (errmsg_internal("SSL: read alert (0x%04x): \"%s\"", args, desc)));
                               1289                 :             26 :             break;
                               1290                 :            164 :         case SSL_CB_WRITE_ALERT:
                               1291         [ -  + ]:            164 :             ereport(DEBUG4,
                               1292                 :                :                     (errmsg_internal("SSL: write alert (0x%04x): \"%s\"", args, desc)));
 3534                          1293                 :            164 :             break;
                               1294                 :                :     }
 3527                          1295                 :           4629 : }
                               1296                 :                : 
                               1297                 :                : /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */
                               1298                 :                : static const unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR;
                               1299                 :                : 
                               1300                 :                : /*
                               1301                 :                :  * Server callback for ALPN negotiation. We use the standard "helper" function
                               1302                 :                :  * even though currently we only accept one value.
                               1303                 :                :  */
                               1304                 :                : static int
    6 heikki.linnakangas@i     1305                 :GNC         360 : alpn_cb(SSL *ssl,
                               1306                 :                :         const unsigned char **out,
                               1307                 :                :         unsigned char *outlen,
                               1308                 :                :         const unsigned char *in,
                               1309                 :                :         unsigned int inlen,
                               1310                 :                :         void *userdata)
                               1311                 :                : {
                               1312                 :                :     /*
                               1313                 :                :      * Why does OpenSSL provide a helper function that requires a nonconst
                               1314                 :                :      * vector when the callback is declared to take a const vector? What are
                               1315                 :                :      * we to do with that?
                               1316                 :                :      */
                               1317                 :                :     int         retval;
                               1318                 :                : 
                               1319         [ -  + ]:            360 :     Assert(userdata != NULL);
                               1320         [ -  + ]:            360 :     Assert(out != NULL);
                               1321         [ -  + ]:            360 :     Assert(outlen != NULL);
                               1322         [ -  + ]:            360 :     Assert(in != NULL);
                               1323                 :                : 
                               1324                 :            360 :     retval = SSL_select_next_proto((unsigned char **) out, outlen,
                               1325                 :                :                                    alpn_protos, sizeof(alpn_protos),
                               1326                 :                :                                    in, inlen);
                               1327   [ +  -  +  -  :            360 :     if (*out == NULL || *outlen > sizeof(alpn_protos) || *outlen <= 0)
                                              -  + ]
    6 heikki.linnakangas@i     1328                 :UNC           0 :         return SSL_TLSEXT_ERR_NOACK;    /* can't happen */
                               1329                 :                : 
    6 heikki.linnakangas@i     1330         [ +  - ]:GNC         360 :     if (retval == OPENSSL_NPN_NEGOTIATED)
                               1331                 :            360 :         return SSL_TLSEXT_ERR_OK;
    6 heikki.linnakangas@i     1332         [ #  # ]:UNC           0 :     else if (retval == OPENSSL_NPN_NO_OVERLAP)
                               1333                 :              0 :         return SSL_TLSEXT_ERR_NOACK;
                               1334                 :                :     else
                               1335                 :              0 :         return SSL_TLSEXT_ERR_NOACK;
                               1336                 :                : }
                               1337                 :                : 
                               1338                 :                : 
                               1339                 :                : /*
                               1340                 :                :  * Set DH parameters for generating ephemeral DH keys.  The
                               1341                 :                :  * DH parameters can take a long time to compute, so they must be
                               1342                 :                :  * precomputed.
                               1343                 :                :  *
                               1344                 :                :  * Since few sites will bother to create a parameter file, we also
                               1345                 :                :  * provide a fallback to the parameters provided by the OpenSSL
                               1346                 :                :  * project.
                               1347                 :                :  *
                               1348                 :                :  * These values can be static (once loaded or computed) since the
                               1349                 :                :  * OpenSSL library can efficiently generate random keys from the
                               1350                 :                :  * information provided.
                               1351                 :                :  */
                               1352                 :                : static bool
 2449 heikki.linnakangas@i     1353                 :CBC          25 : initialize_dh(SSL_CTX *context, bool isServerStart)
                               1354                 :                : {
                               1355                 :             25 :     DH         *dh = NULL;
                               1356                 :                : 
                               1357                 :             25 :     SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE);
                               1358                 :                : 
                               1359         [ -  + ]:             25 :     if (ssl_dh_params_file[0])
 2449 heikki.linnakangas@i     1360                 :UBC           0 :         dh = load_dh_file(ssl_dh_params_file, isServerStart);
 2449 heikki.linnakangas@i     1361         [ +  - ]:CBC          25 :     if (!dh)
 2277 peter_e@gmx.net          1362                 :             25 :         dh = load_dh_buffer(FILE_DH2048, sizeof(FILE_DH2048));
 2449 heikki.linnakangas@i     1363         [ -  + ]:             25 :     if (!dh)
                               1364                 :                :     {
 2449 heikki.linnakangas@i     1365   [ #  #  #  # ]:UBC           0 :         ereport(isServerStart ? FATAL : LOG,
                               1366                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                               1367                 :                :                  errmsg("DH: could not load DH parameters")));
                               1368                 :              0 :         return false;
                               1369                 :                :     }
                               1370                 :                : 
 2449 heikki.linnakangas@i     1371         [ -  + ]:CBC          25 :     if (SSL_CTX_set_tmp_dh(context, dh) != 1)
                               1372                 :                :     {
 2449 heikki.linnakangas@i     1373   [ #  #  #  # ]:UBC           0 :         ereport(isServerStart ? FATAL : LOG,
                               1374                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                               1375                 :                :                  errmsg("DH: could not set DH parameters: %s",
                               1376                 :                :                         SSLerrmessage(ERR_get_error()))));
 1583 michael@paquier.xyz      1377                 :              0 :         DH_free(dh);
 2449 heikki.linnakangas@i     1378                 :              0 :         return false;
                               1379                 :                :     }
                               1380                 :                : 
 1583 michael@paquier.xyz      1381                 :CBC          25 :     DH_free(dh);
 2449 heikki.linnakangas@i     1382                 :             25 :     return true;
                               1383                 :                : }
                               1384                 :                : 
                               1385                 :                : /*
                               1386                 :                :  * Set ECDH parameters for generating ephemeral Elliptic Curve DH
                               1387                 :                :  * keys.  This is much simpler than the DH parameters, as we just
                               1388                 :                :  * need to provide the name of the curve to OpenSSL.
                               1389                 :                :  */
                               1390                 :                : static bool
 2657 tgl@sss.pgh.pa.us        1391                 :             25 : initialize_ecdh(SSL_CTX *context, bool isServerStart)
                               1392                 :                : {
                               1393                 :                : #ifndef OPENSSL_NO_ECDH
                               1394                 :                :     EC_KEY     *ecdh;
                               1395                 :                :     int         nid;
                               1396                 :                : 
 3527 heikki.linnakangas@i     1397                 :             25 :     nid = OBJ_sn2nid(SSLECDHCurve);
                               1398         [ -  + ]:             25 :     if (!nid)
                               1399                 :                :     {
 2657 tgl@sss.pgh.pa.us        1400   [ #  #  #  # ]:UBC           0 :         ereport(isServerStart ? FATAL : LOG,
                               1401                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                               1402                 :                :                  errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve)));
 2659                          1403                 :              0 :         return false;
                               1404                 :                :     }
                               1405                 :                : 
 3527 heikki.linnakangas@i     1406                 :CBC          25 :     ecdh = EC_KEY_new_by_curve_name(nid);
                               1407         [ -  + ]:             25 :     if (!ecdh)
                               1408                 :                :     {
 2657 tgl@sss.pgh.pa.us        1409   [ #  #  #  # ]:UBC           0 :         ereport(isServerStart ? FATAL : LOG,
                               1410                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                               1411                 :                :                  errmsg("ECDH: could not create key")));
 2659                          1412                 :              0 :         return false;
                               1413                 :                :     }
                               1414                 :                : 
 2659 tgl@sss.pgh.pa.us        1415                 :CBC          25 :     SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
                               1416                 :             25 :     SSL_CTX_set_tmp_ecdh(context, ecdh);
 3527 heikki.linnakangas@i     1417                 :             25 :     EC_KEY_free(ecdh);
                               1418                 :                : #endif
                               1419                 :                : 
 2659 tgl@sss.pgh.pa.us        1420                 :             25 :     return true;
                               1421                 :                : }
                               1422                 :                : 
                               1423                 :                : /*
                               1424                 :                :  * Obtain reason string for passed SSL errcode
                               1425                 :                :  *
                               1426                 :                :  * ERR_get_error() is used by caller to get errcode to pass here.
                               1427                 :                :  *
                               1428                 :                :  * Some caution is needed here since ERR_reason_error_string will return NULL
                               1429                 :                :  * if it doesn't recognize the error code, or (in OpenSSL >= 3) if the code
                               1430                 :                :  * represents a system errno value.  We don't want to return NULL ever.
                               1431                 :                :  */
                               1432                 :                : static const char *
 2928 peter_e@gmx.net          1433                 :             16 : SSLerrmessage(unsigned long ecode)
                               1434                 :                : {
                               1435                 :                :     const char *errreason;
                               1436                 :                :     static char errbuf[36];
                               1437                 :                : 
                               1438         [ -  + ]:             16 :     if (ecode == 0)
 3534 heikki.linnakangas@i     1439                 :UBC           0 :         return _("no SSL error reported");
 2928 peter_e@gmx.net          1440                 :CBC          16 :     errreason = ERR_reason_error_string(ecode);
 3534 heikki.linnakangas@i     1441         [ +  - ]:             16 :     if (errreason != NULL)
                               1442                 :             16 :         return errreason;
                               1443                 :                : 
                               1444                 :                :     /*
                               1445                 :                :      * In OpenSSL 3.0.0 and later, ERR_reason_error_string randomly refuses to
                               1446                 :                :      * map system errno values.  We can cover that shortcoming with this bit
                               1447                 :                :      * of code.  Older OpenSSL versions don't have the ERR_SYSTEM_ERROR macro,
                               1448                 :                :      * but that's okay because they don't have the shortcoming either.
                               1449                 :                :      */
                               1450                 :                : #ifdef ERR_SYSTEM_ERROR
   38 tgl@sss.pgh.pa.us        1451         [ #  # ]:UBC           0 :     if (ERR_SYSTEM_ERROR(ecode))
                               1452                 :              0 :         return strerror(ERR_GET_REASON(ecode));
                               1453                 :                : #endif
                               1454                 :                : 
                               1455                 :                :     /* No choice but to report the numeric ecode */
 2928 peter_e@gmx.net          1456                 :              0 :     snprintf(errbuf, sizeof(errbuf), _("SSL error code %lu"), ecode);
 3534 heikki.linnakangas@i     1457                 :              0 :     return errbuf;
                               1458                 :                : }
                               1459                 :                : 
                               1460                 :                : int
 3290 magnus@hagander.net      1461                 :CBC         254 : be_tls_get_cipher_bits(Port *port)
                               1462                 :                : {
                               1463                 :                :     int         bits;
                               1464                 :                : 
                               1465         [ +  - ]:            254 :     if (port->ssl)
                               1466                 :                :     {
                               1467                 :            254 :         SSL_get_cipher_bits(port->ssl, &bits);
                               1468                 :            254 :         return bits;
                               1469                 :                :     }
                               1470                 :                :     else
 3290 magnus@hagander.net      1471                 :UBC           0 :         return 0;
                               1472                 :                : }
                               1473                 :                : 
                               1474                 :                : const char *
 2271 peter_e@gmx.net          1475                 :CBC         255 : be_tls_get_version(Port *port)
                               1476                 :                : {
 3290 magnus@hagander.net      1477         [ +  - ]:            255 :     if (port->ssl)
 2271 peter_e@gmx.net          1478                 :            255 :         return SSL_get_version(port->ssl);
                               1479                 :                :     else
 2271 peter_e@gmx.net          1480                 :UBC           0 :         return NULL;
                               1481                 :                : }
                               1482                 :                : 
                               1483                 :                : const char *
 2271 peter_e@gmx.net          1484                 :CBC         255 : be_tls_get_cipher(Port *port)
                               1485                 :                : {
 3290 magnus@hagander.net      1486         [ +  - ]:            255 :     if (port->ssl)
 2271 peter_e@gmx.net          1487                 :            255 :         return SSL_get_cipher(port->ssl);
                               1488                 :                :     else
 2271 peter_e@gmx.net          1489                 :UBC           0 :         return NULL;
                               1490                 :                : }
                               1491                 :                : 
                               1492                 :                : void
 1899 peter@eisentraut.org     1493                 :CBC         127 : be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len)
                               1494                 :                : {
 3290 magnus@hagander.net      1495         [ +  + ]:            127 :     if (port->peer)
                               1496                 :             27 :         strlcpy(ptr, X509_NAME_to_cstring(X509_get_subject_name(port->peer)), len);
                               1497                 :                :     else
                               1498                 :            100 :         ptr[0] = '\0';
                               1499                 :            127 : }
                               1500                 :                : 
                               1501                 :                : void
 1899 peter@eisentraut.org     1502                 :            128 : be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len)
                               1503                 :                : {
                               1504         [ +  + ]:            128 :     if (port->peer)
                               1505                 :             28 :         strlcpy(ptr, X509_NAME_to_cstring(X509_get_issuer_name(port->peer)), len);
                               1506                 :                :     else
                               1507                 :            100 :         ptr[0] = '\0';
                               1508                 :            128 : }
                               1509                 :                : 
                               1510                 :                : void
                               1511                 :            128 : be_tls_get_peer_serial(Port *port, char *ptr, size_t len)
                               1512                 :                : {
                               1513         [ +  + ]:            128 :     if (port->peer)
                               1514                 :                :     {
                               1515                 :                :         ASN1_INTEGER *serial;
                               1516                 :                :         BIGNUM     *b;
                               1517                 :                :         char       *decimal;
                               1518                 :                : 
                               1519                 :             28 :         serial = X509_get_serialNumber(port->peer);
                               1520                 :             28 :         b = ASN1_INTEGER_to_BN(serial, NULL);
                               1521                 :             28 :         decimal = BN_bn2dec(b);
                               1522                 :                : 
                               1523                 :             28 :         BN_free(b);
                               1524                 :             28 :         strlcpy(ptr, decimal, len);
                               1525                 :             28 :         OPENSSL_free(decimal);
                               1526                 :                :     }
                               1527                 :                :     else
                               1528                 :            100 :         ptr[0] = '\0';
                               1529                 :            128 : }
                               1530                 :                : 
                               1531                 :                : char *
 2292 peter_e@gmx.net          1532                 :              4 : be_tls_get_certificate_hash(Port *port, size_t *len)
                               1533                 :                : {
                               1534                 :                :     X509       *server_cert;
                               1535                 :                :     char       *cert_hash;
                               1536                 :              4 :     const EVP_MD *algo_type = NULL;
                               1537                 :                :     unsigned char hash[EVP_MAX_MD_SIZE];    /* size for SHA-512 */
                               1538                 :                :     unsigned int hash_size;
                               1539                 :                :     int         algo_nid;
                               1540                 :                : 
                               1541                 :              4 :     *len = 0;
                               1542                 :              4 :     server_cert = SSL_get_certificate(port->ssl);
                               1543         [ -  + ]:              4 :     if (server_cert == NULL)
 2292 peter_e@gmx.net          1544                 :UBC           0 :         return NULL;
                               1545                 :                : 
                               1546                 :                :     /*
                               1547                 :                :      * Get the signature algorithm of the certificate to determine the hash
                               1548                 :                :      * algorithm to use for the result.  Prefer X509_get_signature_info(),
                               1549                 :                :      * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
                               1550                 :                :      */
                               1551                 :                : #if HAVE_X509_GET_SIGNATURE_INFO
  424 michael@paquier.xyz      1552         [ -  + ]:CBC           4 :     if (!X509_get_signature_info(server_cert, &algo_nid, NULL, NULL, NULL))
                               1553                 :                : #else
                               1554                 :                :     if (!OBJ_find_sigid_algs(X509_get_signature_nid(server_cert),
                               1555                 :                :                              &algo_nid, NULL))
                               1556                 :                : #endif
 2292 peter_e@gmx.net          1557         [ #  # ]:UBC           0 :         elog(ERROR, "could not determine server certificate signature algorithm");
                               1558                 :                : 
                               1559                 :                :     /*
                               1560                 :                :      * The TLS server's certificate bytes need to be hashed with SHA-256 if
                               1561                 :                :      * its signature algorithm is MD5 or SHA-1 as per RFC 5929
                               1562                 :                :      * (https://tools.ietf.org/html/rfc5929#section-4.1).  If something else
                               1563                 :                :      * is used, the same hash as the signature algorithm is used.
                               1564                 :                :      */
 2292 peter_e@gmx.net          1565         [ -  + ]:CBC           4 :     switch (algo_nid)
                               1566                 :                :     {
 2292 peter_e@gmx.net          1567                 :UBC           0 :         case NID_md5:
                               1568                 :                :         case NID_sha1:
                               1569                 :              0 :             algo_type = EVP_sha256();
                               1570                 :              0 :             break;
 2292 peter_e@gmx.net          1571                 :CBC           4 :         default:
                               1572                 :              4 :             algo_type = EVP_get_digestbynid(algo_nid);
                               1573         [ -  + ]:              4 :             if (algo_type == NULL)
 2292 peter_e@gmx.net          1574         [ #  # ]:UBC           0 :                 elog(ERROR, "could not find digest for NID %s",
                               1575                 :                :                      OBJ_nid2sn(algo_nid));
 2292 peter_e@gmx.net          1576                 :CBC           4 :             break;
                               1577                 :                :     }
                               1578                 :                : 
                               1579                 :                :     /* generate and save the certificate hash */
                               1580         [ -  + ]:              4 :     if (!X509_digest(server_cert, algo_type, hash, &hash_size))
 2292 peter_e@gmx.net          1581         [ #  # ]:UBC           0 :         elog(ERROR, "could not generate server certificate hash");
                               1582                 :                : 
 2292 peter_e@gmx.net          1583                 :CBC           4 :     cert_hash = palloc(hash_size);
                               1584                 :              4 :     memcpy(cert_hash, hash, hash_size);
                               1585                 :              4 :     *len = hash_size;
                               1586                 :                : 
                               1587                 :              4 :     return cert_hash;
                               1588                 :                : }
                               1589                 :                : 
                               1590                 :                : /*
                               1591                 :                :  * Convert an X509 subject name to a cstring.
                               1592                 :                :  *
                               1593                 :                :  */
                               1594                 :                : static char *
 3290 magnus@hagander.net      1595                 :             65 : X509_NAME_to_cstring(X509_NAME *name)
                               1596                 :                : {
                               1597                 :             65 :     BIO        *membuf = BIO_new(BIO_s_mem());
                               1598                 :                :     int         i,
                               1599                 :                :                 nid,
                               1600                 :             65 :                 count = X509_NAME_entry_count(name);
                               1601                 :                :     X509_NAME_ENTRY *e;
                               1602                 :                :     ASN1_STRING *v;
                               1603                 :                :     const char *field_name;
                               1604                 :                :     size_t      size;
                               1605                 :                :     char        nullterm;
                               1606                 :                :     char       *sp;
                               1607                 :                :     char       *dp;
                               1608                 :                :     char       *result;
                               1609                 :                : 
 1258                          1610         [ -  + ]:             65 :     if (membuf == NULL)
 1258 magnus@hagander.net      1611         [ #  # ]:UBC           0 :         ereport(ERROR,
                               1612                 :                :                 (errcode(ERRCODE_OUT_OF_MEMORY),
                               1613                 :                :                  errmsg("could not create BIO")));
                               1614                 :                : 
 3290 magnus@hagander.net      1615                 :CBC          65 :     (void) BIO_set_close(membuf, BIO_CLOSE);
                               1616         [ +  + ]:            141 :     for (i = 0; i < count; i++)
                               1617                 :                :     {
                               1618                 :             76 :         e = X509_NAME_get_entry(name, i);
                               1619                 :             76 :         nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e));
 1258                          1620         [ -  + ]:             76 :         if (nid == NID_undef)
 1258 magnus@hagander.net      1621         [ #  # ]:UBC           0 :             ereport(ERROR,
                               1622                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1623                 :                :                      errmsg("could not get NID for ASN1_OBJECT object")));
 3290 magnus@hagander.net      1624                 :CBC          76 :         v = X509_NAME_ENTRY_get_data(e);
                               1625                 :             76 :         field_name = OBJ_nid2sn(nid);
 1258                          1626         [ -  + ]:             76 :         if (field_name == NULL)
 3290 magnus@hagander.net      1627                 :UBC           0 :             field_name = OBJ_nid2ln(nid);
 1258 magnus@hagander.net      1628         [ -  + ]:CBC          76 :         if (field_name == NULL)
 1258 magnus@hagander.net      1629         [ #  # ]:UBC           0 :             ereport(ERROR,
                               1630                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1631                 :                :                      errmsg("could not convert NID %d to an ASN1_OBJECT structure", nid)));
 3290 magnus@hagander.net      1632                 :CBC          76 :         BIO_printf(membuf, "/%s=", field_name);
                               1633                 :             76 :         ASN1_STRING_print_ex(membuf, v,
                               1634                 :                :                              ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB)
                               1635                 :                :                               | ASN1_STRFLGS_UTF8_CONVERT));
                               1636                 :                :     }
                               1637                 :                : 
                               1638                 :                :     /* ensure null termination of the BIO's content */
                               1639                 :             65 :     nullterm = '\0';
                               1640                 :             65 :     BIO_write(membuf, &nullterm, 1);
                               1641                 :             65 :     size = BIO_get_mem_data(membuf, &sp);
                               1642                 :             65 :     dp = pg_any_to_server(sp, size - 1, PG_UTF8);
                               1643                 :                : 
                               1644                 :             65 :     result = pstrdup(dp);
                               1645         [ -  + ]:             65 :     if (dp != sp)
 3290 magnus@hagander.net      1646                 :UBC           0 :         pfree(dp);
 1258 magnus@hagander.net      1647         [ -  + ]:CBC          65 :     if (BIO_free(membuf) != 1)
 1258 magnus@hagander.net      1648         [ #  # ]:UBC           0 :         elog(ERROR, "could not free OpenSSL BIO structure");
                               1649                 :                : 
 3290 magnus@hagander.net      1650                 :CBC          65 :     return result;
                               1651                 :                : }
                               1652                 :                : 
                               1653                 :                : /*
                               1654                 :                :  * Convert TLS protocol version GUC enum to OpenSSL values
                               1655                 :                :  *
                               1656                 :                :  * This is a straightforward one-to-one mapping, but doing it this way makes
                               1657                 :                :  * the definitions of ssl_min_protocol_version and ssl_max_protocol_version
                               1658                 :                :  * independent of OpenSSL availability and version.
                               1659                 :                :  *
                               1660                 :                :  * If a version is passed that is not supported by the current OpenSSL
                               1661                 :                :  * version, then we return -1.  If a nonnegative value is returned,
                               1662                 :                :  * subsequent code can assume it's working with a supported version.
                               1663                 :                :  *
                               1664                 :                :  * Note: this is rather similar to libpq's routine in fe-secure-openssl.c,
                               1665                 :                :  * so make sure to update both routines if changing this one.
                               1666                 :                :  */
                               1667                 :                : static int
 1483 michael@paquier.xyz      1668                 :             27 : ssl_protocol_version_to_openssl(int v)
                               1669                 :                : {
 1972 peter_e@gmx.net          1670   [ -  -  +  +  :             27 :     switch (v)
                                              -  - ]
                               1671                 :                :     {
 1972 peter_e@gmx.net          1672                 :UBC           0 :         case PG_TLS_ANY:
                               1673                 :              0 :             return 0;
                               1674                 :              0 :         case PG_TLS1_VERSION:
                               1675                 :              0 :             return TLS1_VERSION;
 1972 peter_e@gmx.net          1676                 :CBC           1 :         case PG_TLS1_1_VERSION:
                               1677                 :                : #ifdef TLS1_1_VERSION
                               1678                 :              1 :             return TLS1_1_VERSION;
                               1679                 :                : #else
                               1680                 :                :             break;
                               1681                 :                : #endif
                               1682                 :             26 :         case PG_TLS1_2_VERSION:
                               1683                 :                : #ifdef TLS1_2_VERSION
                               1684                 :             26 :             return TLS1_2_VERSION;
                               1685                 :                : #else
                               1686                 :                :             break;
                               1687                 :                : #endif
 1972 peter_e@gmx.net          1688                 :UBC           0 :         case PG_TLS1_3_VERSION:
                               1689                 :                : #ifdef TLS1_3_VERSION
                               1690                 :              0 :             return TLS1_3_VERSION;
                               1691                 :                : #else
                               1692                 :                :             break;
                               1693                 :                : #endif
                               1694                 :                :     }
                               1695                 :                : 
                               1696                 :              0 :     return -1;
                               1697                 :                : }
                               1698                 :                : 
                               1699                 :                : /*
                               1700                 :                :  * Likewise provide a mapping to strings.
                               1701                 :                :  */
                               1702                 :                : static const char *
 1387 tgl@sss.pgh.pa.us        1703                 :              0 : ssl_protocol_version_to_string(int v)
                               1704                 :                : {
                               1705   [ #  #  #  #  :              0 :     switch (v)
                                              #  # ]
                               1706                 :                :     {
                               1707                 :              0 :         case PG_TLS_ANY:
                               1708                 :              0 :             return "any";
                               1709                 :              0 :         case PG_TLS1_VERSION:
                               1710                 :              0 :             return "TLSv1";
                               1711                 :              0 :         case PG_TLS1_1_VERSION:
                               1712                 :              0 :             return "TLSv1.1";
                               1713                 :              0 :         case PG_TLS1_2_VERSION:
                               1714                 :              0 :             return "TLSv1.2";
                               1715                 :              0 :         case PG_TLS1_3_VERSION:
                               1716                 :              0 :             return "TLSv1.3";
                               1717                 :                :     }
                               1718                 :                : 
                               1719                 :              0 :     return "(unrecognized)";
                               1720                 :                : }
                               1721                 :                : 
                               1722                 :                : 
                               1723                 :                : static void
 1481 andrew@dunslane.net      1724                 :CBC          25 : default_openssl_tls_init(SSL_CTX *context, bool isServerStart)
                               1725                 :                : {
                               1726         [ +  + ]:             25 :     if (isServerStart)
                               1727                 :                :     {
                               1728         [ +  + ]:             23 :         if (ssl_passphrase_command[0])
                               1729                 :              4 :             SSL_CTX_set_default_passwd_cb(context, ssl_external_passwd_cb);
                               1730                 :                :     }
                               1731                 :                :     else
                               1732                 :                :     {
 1481 andrew@dunslane.net      1733   [ -  +  -  - ]:GBC           2 :         if (ssl_passphrase_command[0] && ssl_passphrase_command_supports_reload)
 1481 andrew@dunslane.net      1734                 :UBC           0 :             SSL_CTX_set_default_passwd_cb(context, ssl_external_passwd_cb);
                               1735                 :                :         else
                               1736                 :                : 
                               1737                 :                :             /*
                               1738                 :                :              * If reloading and no external command is configured, override
                               1739                 :                :              * OpenSSL's default handling of passphrase-protected files,
                               1740                 :                :              * because we don't want to prompt for a passphrase in an
                               1741                 :                :              * already-running server.
                               1742                 :                :              */
 1481 andrew@dunslane.net      1743                 :GBC           2 :             SSL_CTX_set_default_passwd_cb(context, dummy_ssl_passwd_cb);
                               1744                 :                :     }
 1481 andrew@dunslane.net      1745                 :CBC          25 : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622