LCOV - code coverage report
Current view: top level - src/interfaces/libpq - fe-secure-openssl.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 304 605 50.2 %
Date: 2020-05-25 05:06:35 Functions: 22 29 75.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * fe-secure-openssl.c
       4             :  *    OpenSSL support
       5             :  *
       6             :  *
       7             :  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
       8             :  * Portions Copyright (c) 1994, Regents of the University of California
       9             :  *
      10             :  *
      11             :  * IDENTIFICATION
      12             :  *    src/interfaces/libpq/fe-secure-openssl.c
      13             :  *
      14             :  * NOTES
      15             :  *
      16             :  *    We don't provide informational callbacks here (like
      17             :  *    info_cb() in be-secure.c), since there's no good mechanism to
      18             :  *    display such information to the user.
      19             :  *
      20             :  *-------------------------------------------------------------------------
      21             :  */
      22             : 
      23             : #include "postgres_fe.h"
      24             : 
      25             : #include <signal.h>
      26             : #include <fcntl.h>
      27             : #include <ctype.h>
      28             : 
      29             : #include "libpq-fe.h"
      30             : #include "fe-auth.h"
      31             : #include "fe-secure-common.h"
      32             : #include "libpq-int.h"
      33             : #include "common/openssl.h"
      34             : 
      35             : #ifdef WIN32
      36             : #include "win32.h"
      37             : #else
      38             : #include <sys/socket.h>
      39             : #include <unistd.h>
      40             : #include <netdb.h>
      41             : #include <netinet/in.h>
      42             : #ifdef HAVE_NETINET_TCP_H
      43             : #include <netinet/tcp.h>
      44             : #endif
      45             : #include <arpa/inet.h>
      46             : #endif
      47             : 
      48             : #include <sys/stat.h>
      49             : 
      50             : #ifdef ENABLE_THREAD_SAFETY
      51             : #ifdef WIN32
      52             : #include "pthread-win32.h"
      53             : #else
      54             : #include <pthread.h>
      55             : #endif
      56             : #endif
      57             : 
      58             : #include <openssl/ssl.h>
      59             : #include <openssl/conf.h>
      60             : #ifdef USE_SSL_ENGINE
      61             : #include <openssl/engine.h>
      62             : #endif
      63             : #include <openssl/x509v3.h>
      64             : 
      65             : static int  verify_cb(int ok, X509_STORE_CTX *ctx);
      66             : static int  openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
      67             :                                                               ASN1_STRING *name,
      68             :                                                               char **store_name);
      69             : static void destroy_ssl_system(void);
      70             : static int  initialize_SSL(PGconn *conn);
      71             : static PostgresPollingStatusType open_client_SSL(PGconn *);
      72             : static char *SSLerrmessage(unsigned long ecode);
      73             : static void SSLerrfree(char *buf);
      74             : static int  PQssl_passwd_cb(char *buf, int size, int rwflag, void *userdata);
      75             : 
      76             : static int  my_sock_read(BIO *h, char *buf, int size);
      77             : static int  my_sock_write(BIO *h, const char *buf, int size);
      78             : static BIO_METHOD *my_BIO_s_socket(void);
      79             : static int  my_SSL_set_fd(PGconn *conn, int fd);
      80             : 
      81             : 
      82             : static bool pq_init_ssl_lib = true;
      83             : static bool pq_init_crypto_lib = true;
      84             : 
      85             : static bool ssl_lib_initialized = false;
      86             : 
      87             : #ifdef ENABLE_THREAD_SAFETY
      88             : static long ssl_open_connections = 0;
      89             : 
      90             : #ifndef WIN32
      91             : static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER;
      92             : #else
      93             : static pthread_mutex_t ssl_config_mutex = NULL;
      94             : static long win32_ssl_create_mutex = 0;
      95             : #endif
      96             : #endif                          /* ENABLE_THREAD_SAFETY */
      97             : 
      98             : static PQsslKeyPassHook_OpenSSL_type PQsslKeyPassHook = NULL;
      99             : static int  ssl_protocol_version_to_openssl(const char *protocol);
     100             : 
     101             : /* ------------------------------------------------------------ */
     102             : /*           Procedures common to all secure sessions           */
     103             : /* ------------------------------------------------------------ */
     104             : 
     105             : void
     106           0 : pgtls_init_library(bool do_ssl, int do_crypto)
     107             : {
     108             : #ifdef ENABLE_THREAD_SAFETY
     109             : 
     110             :     /*
     111             :      * Disallow changing the flags while we have open connections, else we'd
     112             :      * get completely confused.
     113             :      */
     114           0 :     if (ssl_open_connections != 0)
     115           0 :         return;
     116             : #endif
     117             : 
     118           0 :     pq_init_ssl_lib = do_ssl;
     119           0 :     pq_init_crypto_lib = do_crypto;
     120             : }
     121             : 
     122             : PostgresPollingStatusType
     123         314 : pgtls_open_client(PGconn *conn)
     124             : {
     125             :     /* First time through? */
     126         314 :     if (conn->ssl == NULL)
     127             :     {
     128             :         /*
     129             :          * Create a connection-specific SSL object, and load client
     130             :          * certificate, private key, and trusted CA certs.
     131             :          */
     132         110 :         if (initialize_SSL(conn) != 0)
     133             :         {
     134             :             /* initialize_SSL already put a message in conn->errorMessage */
     135           8 :             pgtls_close(conn);
     136           8 :             return PGRES_POLLING_FAILED;
     137             :         }
     138             :     }
     139             : 
     140             :     /* Begin or continue the actual handshake */
     141         306 :     return open_client_SSL(conn);
     142             : }
     143             : 
     144             : ssize_t
     145         314 : pgtls_read(PGconn *conn, void *ptr, size_t len)
     146             : {
     147             :     ssize_t     n;
     148         314 :     int         result_errno = 0;
     149             :     char        sebuf[PG_STRERROR_R_BUFLEN];
     150             :     int         err;
     151             :     unsigned long ecode;
     152             : 
     153         314 : rloop:
     154             : 
     155             :     /*
     156             :      * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
     157             :      * queue.  In general, the current thread's error queue must be empty
     158             :      * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
     159             :      * not work reliably.  Since the possibility exists that other OpenSSL
     160             :      * clients running in the same thread but not under our control will fail
     161             :      * to call ERR_get_error() themselves (after their own I/O operations),
     162             :      * pro-actively clear the per-thread error queue now.
     163             :      */
     164         314 :     SOCK_ERRNO_SET(0);
     165         314 :     ERR_clear_error();
     166         314 :     n = SSL_read(conn->ssl, ptr, len);
     167         314 :     err = SSL_get_error(conn->ssl, n);
     168             : 
     169             :     /*
     170             :      * Other clients of OpenSSL may fail to call ERR_get_error(), but we
     171             :      * always do, so as to not cause problems for OpenSSL clients that don't
     172             :      * call ERR_clear_error() defensively.  Be sure that this happens by
     173             :      * calling now.  SSL_get_error() relies on the OpenSSL per-thread error
     174             :      * queue being intact, so this is the earliest possible point
     175             :      * ERR_get_error() may be called.
     176             :      */
     177         314 :     ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
     178         314 :     switch (err)
     179             :     {
     180         146 :         case SSL_ERROR_NONE:
     181         146 :             if (n < 0)
     182             :             {
     183             :                 /* Not supposed to happen, so we don't translate the msg */
     184           0 :                 printfPQExpBuffer(&conn->errorMessage,
     185             :                                   "SSL_read failed but did not provide error information\n");
     186             :                 /* assume the connection is broken */
     187           0 :                 result_errno = ECONNRESET;
     188             :             }
     189         146 :             break;
     190         164 :         case SSL_ERROR_WANT_READ:
     191         164 :             n = 0;
     192         164 :             break;
     193           0 :         case SSL_ERROR_WANT_WRITE:
     194             : 
     195             :             /*
     196             :              * Returning 0 here would cause caller to wait for read-ready,
     197             :              * which is not correct since what SSL wants is wait for
     198             :              * write-ready.  The former could get us stuck in an infinite
     199             :              * wait, so don't risk it; busy-loop instead.
     200             :              */
     201           0 :             goto rloop;
     202           0 :         case SSL_ERROR_SYSCALL:
     203           0 :             if (n < 0)
     204             :             {
     205           0 :                 result_errno = SOCK_ERRNO;
     206           0 :                 if (result_errno == EPIPE ||
     207             :                     result_errno == ECONNRESET)
     208           0 :                     printfPQExpBuffer(&conn->errorMessage,
     209           0 :                                       libpq_gettext("server closed the connection unexpectedly\n"
     210             :                                                     "\tThis probably means the server terminated abnormally\n"
     211             :                                                     "\tbefore or while processing the request.\n"));
     212             :                 else
     213           0 :                     printfPQExpBuffer(&conn->errorMessage,
     214           0 :                                       libpq_gettext("SSL SYSCALL error: %s\n"),
     215             :                                       SOCK_STRERROR(result_errno,
     216             :                                                     sebuf, sizeof(sebuf)));
     217             :             }
     218             :             else
     219             :             {
     220           0 :                 printfPQExpBuffer(&conn->errorMessage,
     221           0 :                                   libpq_gettext("SSL SYSCALL error: EOF detected\n"));
     222             :                 /* assume the connection is broken */
     223           0 :                 result_errno = ECONNRESET;
     224           0 :                 n = -1;
     225             :             }
     226           0 :             break;
     227           4 :         case SSL_ERROR_SSL:
     228             :             {
     229           4 :                 char       *errm = SSLerrmessage(ecode);
     230             : 
     231           4 :                 printfPQExpBuffer(&conn->errorMessage,
     232           4 :                                   libpq_gettext("SSL error: %s\n"), errm);
     233           4 :                 SSLerrfree(errm);
     234             :                 /* assume the connection is broken */
     235           4 :                 result_errno = ECONNRESET;
     236           4 :                 n = -1;
     237           4 :                 break;
     238             :             }
     239           0 :         case SSL_ERROR_ZERO_RETURN:
     240             : 
     241             :             /*
     242             :              * Per OpenSSL documentation, this error code is only returned for
     243             :              * a clean connection closure, so we should not report it as a
     244             :              * server crash.
     245             :              */
     246           0 :             printfPQExpBuffer(&conn->errorMessage,
     247           0 :                               libpq_gettext("SSL connection has been closed unexpectedly\n"));
     248           0 :             result_errno = ECONNRESET;
     249           0 :             n = -1;
     250           0 :             break;
     251           0 :         default:
     252           0 :             printfPQExpBuffer(&conn->errorMessage,
     253           0 :                               libpq_gettext("unrecognized SSL error code: %d\n"),
     254             :                               err);
     255             :             /* assume the connection is broken */
     256           0 :             result_errno = ECONNRESET;
     257           0 :             n = -1;
     258           0 :             break;
     259             :     }
     260             : 
     261             :     /* ensure we return the intended errno to caller */
     262         314 :     SOCK_ERRNO_SET(result_errno);
     263             : 
     264         314 :     return n;
     265             : }
     266             : 
     267             : bool
     268         456 : pgtls_read_pending(PGconn *conn)
     269             : {
     270         456 :     return SSL_pending(conn->ssl) > 0;
     271             : }
     272             : 
     273             : ssize_t
     274         212 : pgtls_write(PGconn *conn, const void *ptr, size_t len)
     275             : {
     276             :     ssize_t     n;
     277         212 :     int         result_errno = 0;
     278             :     char        sebuf[PG_STRERROR_R_BUFLEN];
     279             :     int         err;
     280             :     unsigned long ecode;
     281             : 
     282         212 :     SOCK_ERRNO_SET(0);
     283         212 :     ERR_clear_error();
     284         212 :     n = SSL_write(conn->ssl, ptr, len);
     285         212 :     err = SSL_get_error(conn->ssl, n);
     286         212 :     ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
     287         212 :     switch (err)
     288             :     {
     289         212 :         case SSL_ERROR_NONE:
     290         212 :             if (n < 0)
     291             :             {
     292             :                 /* Not supposed to happen, so we don't translate the msg */
     293           0 :                 printfPQExpBuffer(&conn->errorMessage,
     294             :                                   "SSL_write failed but did not provide error information\n");
     295             :                 /* assume the connection is broken */
     296           0 :                 result_errno = ECONNRESET;
     297             :             }
     298         212 :             break;
     299           0 :         case SSL_ERROR_WANT_READ:
     300             : 
     301             :             /*
     302             :              * Returning 0 here causes caller to wait for write-ready, which
     303             :              * is not really the right thing, but it's the best we can do.
     304             :              */
     305           0 :             n = 0;
     306           0 :             break;
     307           0 :         case SSL_ERROR_WANT_WRITE:
     308           0 :             n = 0;
     309           0 :             break;
     310           0 :         case SSL_ERROR_SYSCALL:
     311           0 :             if (n < 0)
     312             :             {
     313           0 :                 result_errno = SOCK_ERRNO;
     314           0 :                 if (result_errno == EPIPE || result_errno == ECONNRESET)
     315           0 :                     printfPQExpBuffer(&conn->errorMessage,
     316           0 :                                       libpq_gettext("server closed the connection unexpectedly\n"
     317             :                                                     "\tThis probably means the server terminated abnormally\n"
     318             :                                                     "\tbefore or while processing the request.\n"));
     319             :                 else
     320           0 :                     printfPQExpBuffer(&conn->errorMessage,
     321           0 :                                       libpq_gettext("SSL SYSCALL error: %s\n"),
     322             :                                       SOCK_STRERROR(result_errno,
     323             :                                                     sebuf, sizeof(sebuf)));
     324             :             }
     325             :             else
     326             :             {
     327           0 :                 printfPQExpBuffer(&conn->errorMessage,
     328           0 :                                   libpq_gettext("SSL SYSCALL error: EOF detected\n"));
     329             :                 /* assume the connection is broken */
     330           0 :                 result_errno = ECONNRESET;
     331           0 :                 n = -1;
     332             :             }
     333           0 :             break;
     334           0 :         case SSL_ERROR_SSL:
     335             :             {
     336           0 :                 char       *errm = SSLerrmessage(ecode);
     337             : 
     338           0 :                 printfPQExpBuffer(&conn->errorMessage,
     339           0 :                                   libpq_gettext("SSL error: %s\n"), errm);
     340           0 :                 SSLerrfree(errm);
     341             :                 /* assume the connection is broken */
     342           0 :                 result_errno = ECONNRESET;
     343           0 :                 n = -1;
     344           0 :                 break;
     345             :             }
     346           0 :         case SSL_ERROR_ZERO_RETURN:
     347             : 
     348             :             /*
     349             :              * Per OpenSSL documentation, this error code is only returned for
     350             :              * a clean connection closure, so we should not report it as a
     351             :              * server crash.
     352             :              */
     353           0 :             printfPQExpBuffer(&conn->errorMessage,
     354           0 :                               libpq_gettext("SSL connection has been closed unexpectedly\n"));
     355           0 :             result_errno = ECONNRESET;
     356           0 :             n = -1;
     357           0 :             break;
     358           0 :         default:
     359           0 :             printfPQExpBuffer(&conn->errorMessage,
     360           0 :                               libpq_gettext("unrecognized SSL error code: %d\n"),
     361             :                               err);
     362             :             /* assume the connection is broken */
     363           0 :             result_errno = ECONNRESET;
     364           0 :             n = -1;
     365           0 :             break;
     366             :     }
     367             : 
     368             :     /* ensure we return the intended errno to caller */
     369         212 :     SOCK_ERRNO_SET(result_errno);
     370             : 
     371         212 :     return n;
     372             : }
     373             : 
     374             : #ifdef HAVE_X509_GET_SIGNATURE_NID
     375             : char *
     376           4 : pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
     377             : {
     378             :     X509       *peer_cert;
     379             :     const EVP_MD *algo_type;
     380             :     unsigned char hash[EVP_MAX_MD_SIZE];    /* size for SHA-512 */
     381             :     unsigned int hash_size;
     382             :     int         algo_nid;
     383             :     char       *cert_hash;
     384             : 
     385           4 :     *len = 0;
     386             : 
     387           4 :     if (!conn->peer)
     388           0 :         return NULL;
     389             : 
     390           4 :     peer_cert = conn->peer;
     391             : 
     392             :     /*
     393             :      * Get the signature algorithm of the certificate to determine the hash
     394             :      * algorithm to use for the result.
     395             :      */
     396           4 :     if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert),
     397             :                              &algo_nid, NULL))
     398             :     {
     399           0 :         printfPQExpBuffer(&conn->errorMessage,
     400           0 :                           libpq_gettext("could not determine server certificate signature algorithm\n"));
     401           0 :         return NULL;
     402             :     }
     403             : 
     404             :     /*
     405             :      * The TLS server's certificate bytes need to be hashed with SHA-256 if
     406             :      * its signature algorithm is MD5 or SHA-1 as per RFC 5929
     407             :      * (https://tools.ietf.org/html/rfc5929#section-4.1).  If something else
     408             :      * is used, the same hash as the signature algorithm is used.
     409             :      */
     410           4 :     switch (algo_nid)
     411             :     {
     412           0 :         case NID_md5:
     413             :         case NID_sha1:
     414           0 :             algo_type = EVP_sha256();
     415           0 :             break;
     416           4 :         default:
     417           4 :             algo_type = EVP_get_digestbynid(algo_nid);
     418           4 :             if (algo_type == NULL)
     419             :             {
     420           0 :                 printfPQExpBuffer(&conn->errorMessage,
     421           0 :                                   libpq_gettext("could not find digest for NID %s\n"),
     422             :                                   OBJ_nid2sn(algo_nid));
     423           0 :                 return NULL;
     424             :             }
     425           4 :             break;
     426             :     }
     427             : 
     428           4 :     if (!X509_digest(peer_cert, algo_type, hash, &hash_size))
     429             :     {
     430           0 :         printfPQExpBuffer(&conn->errorMessage,
     431           0 :                           libpq_gettext("could not generate peer certificate hash\n"));
     432           0 :         return NULL;
     433             :     }
     434             : 
     435             :     /* save result */
     436           4 :     cert_hash = malloc(hash_size);
     437           4 :     if (cert_hash == NULL)
     438             :     {
     439           0 :         printfPQExpBuffer(&conn->errorMessage,
     440           0 :                           libpq_gettext("out of memory\n"));
     441           0 :         return NULL;
     442             :     }
     443           4 :     memcpy(cert_hash, hash, hash_size);
     444           4 :     *len = hash_size;
     445             : 
     446           4 :     return cert_hash;
     447             : }
     448             : #endif                          /* HAVE_X509_GET_SIGNATURE_NID */
     449             : 
     450             : /* ------------------------------------------------------------ */
     451             : /*                      OpenSSL specific code                   */
     452             : /* ------------------------------------------------------------ */
     453             : 
     454             : /*
     455             :  *  Certificate verification callback
     456             :  *
     457             :  *  This callback allows us to log intermediate problems during
     458             :  *  verification, but there doesn't seem to be a clean way to get
     459             :  *  our PGconn * structure.  So we can't log anything!
     460             :  *
     461             :  *  This callback also allows us to override the default acceptance
     462             :  *  criteria (e.g., accepting self-signed or expired certs), but
     463             :  *  for now we accept the default checks.
     464             :  */
     465             : static int
     466         240 : verify_cb(int ok, X509_STORE_CTX *ctx)
     467             : {
     468         240 :     return ok;
     469             : }
     470             : 
     471             : 
     472             : /*
     473             :  * OpenSSL-specific wrapper around
     474             :  * pq_verify_peer_name_matches_certificate_name(), converting the ASN1_STRING
     475             :  * into a plain C string.
     476             :  */
     477             : static int
     478          44 : openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *name_entry,
     479             :                                                   char **store_name)
     480             : {
     481             :     int         len;
     482             :     const unsigned char *namedata;
     483             : 
     484             :     /* Should not happen... */
     485          44 :     if (name_entry == NULL)
     486             :     {
     487           0 :         printfPQExpBuffer(&conn->errorMessage,
     488           0 :                           libpq_gettext("SSL certificate's name entry is missing\n"));
     489           0 :         return -1;
     490             :     }
     491             : 
     492             :     /*
     493             :      * GEN_DNS can be only IA5String, equivalent to US ASCII.
     494             :      */
     495             : #ifdef HAVE_ASN1_STRING_GET0_DATA
     496          44 :     namedata = ASN1_STRING_get0_data(name_entry);
     497             : #else
     498             :     namedata = ASN1_STRING_data(name_entry);
     499             : #endif
     500          44 :     len = ASN1_STRING_length(name_entry);
     501             : 
     502             :     /* OK to cast from unsigned to plain char, since it's all ASCII. */
     503          44 :     return pq_verify_peer_name_matches_certificate_name(conn, (const char *) namedata, len, store_name);
     504             : }
     505             : 
     506             : /*
     507             :  *  Verify that the server certificate matches the hostname we connected to.
     508             :  *
     509             :  * The certificate's Common Name and Subject Alternative Names are considered.
     510             :  */
     511             : int
     512          28 : pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
     513             :                                                 int *names_examined,
     514             :                                                 char **first_name)
     515             : {
     516             :     STACK_OF(GENERAL_NAME) * peer_san;
     517             :     int         i;
     518          28 :     int         rc = 0;
     519             : 
     520             :     /*
     521             :      * First, get the Subject Alternative Names (SANs) from the certificate,
     522             :      * and compare them against the originally given hostname.
     523             :      */
     524             :     peer_san = (STACK_OF(GENERAL_NAME) *)
     525          28 :         X509_get_ext_d2i(conn->peer, NID_subject_alt_name, NULL, NULL);
     526             : 
     527          28 :     if (peer_san)
     528             :     {
     529          22 :         int         san_len = sk_GENERAL_NAME_num(peer_san);
     530             : 
     531          50 :         for (i = 0; i < san_len; i++)
     532             :         {
     533          40 :             const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i);
     534             : 
     535          40 :             if (name->type == GEN_DNS)
     536             :             {
     537             :                 char       *alt_name;
     538             : 
     539          40 :                 (*names_examined)++;
     540          40 :                 rc = openssl_verify_peer_name_matches_certificate_name(conn,
     541          40 :                                                                        name->d.dNSName,
     542             :                                                                        &alt_name);
     543             : 
     544          40 :                 if (alt_name)
     545             :                 {
     546          40 :                     if (!*first_name)
     547          22 :                         *first_name = alt_name;
     548             :                     else
     549          18 :                         free(alt_name);
     550             :                 }
     551             :             }
     552          40 :             if (rc != 0)
     553          12 :                 break;
     554             :         }
     555          22 :         sk_GENERAL_NAME_pop_free(peer_san, GENERAL_NAME_free);
     556             :     }
     557             : 
     558             :     /*
     559             :      * If there is no subjectAltName extension of type dNSName, check the
     560             :      * Common Name.
     561             :      *
     562             :      * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
     563             :      * dNSName is present, the CN must be ignored.)
     564             :      */
     565          28 :     if (*names_examined == 0)
     566             :     {
     567             :         X509_NAME  *subject_name;
     568             : 
     569           6 :         subject_name = X509_get_subject_name(conn->peer);
     570           6 :         if (subject_name != NULL)
     571             :         {
     572             :             int         cn_index;
     573             : 
     574           6 :             cn_index = X509_NAME_get_index_by_NID(subject_name,
     575             :                                                   NID_commonName, -1);
     576           6 :             if (cn_index >= 0)
     577             :             {
     578           4 :                 (*names_examined)++;
     579           4 :                 rc = openssl_verify_peer_name_matches_certificate_name(conn,
     580           4 :                                                                        X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, cn_index)),
     581             :                                                                        first_name);
     582             :             }
     583             :         }
     584             :     }
     585             : 
     586          28 :     return rc;
     587             : }
     588             : 
     589             : #if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK)
     590             : /*
     591             :  *  Callback functions for OpenSSL internal locking.  (OpenSSL 1.1.0
     592             :  *  does its own locking, and doesn't need these anymore.  The
     593             :  *  CRYPTO_lock() function was removed in 1.1.0, when the callbacks
     594             :  *  were made obsolete, so we assume that if CRYPTO_lock() exists,
     595             :  *  the callbacks are still required.)
     596             :  */
     597             : 
     598             : static unsigned long
     599             : pq_threadidcallback(void)
     600             : {
     601             :     /*
     602             :      * This is not standards-compliant.  pthread_self() returns pthread_t, and
     603             :      * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
     604             :      * it, so we have to do it.
     605             :      */
     606             :     return (unsigned long) pthread_self();
     607             : }
     608             : 
     609             : static pthread_mutex_t *pq_lockarray;
     610             : 
     611             : static void
     612             : pq_lockingcallback(int mode, int n, const char *file, int line)
     613             : {
     614             :     if (mode & CRYPTO_LOCK)
     615             :     {
     616             :         if (pthread_mutex_lock(&pq_lockarray[n]))
     617             :             PGTHREAD_ERROR("failed to lock mutex");
     618             :     }
     619             :     else
     620             :     {
     621             :         if (pthread_mutex_unlock(&pq_lockarray[n]))
     622             :             PGTHREAD_ERROR("failed to unlock mutex");
     623             :     }
     624             : }
     625             : #endif                          /* ENABLE_THREAD_SAFETY && HAVE_CRYPTO_LOCK */
     626             : 
     627             : /*
     628             :  * Initialize SSL library.
     629             :  *
     630             :  * In threadsafe mode, this includes setting up libcrypto callback functions
     631             :  * to do thread locking.
     632             :  *
     633             :  * If the caller has told us (through PQinitOpenSSL) that he's taking care
     634             :  * of libcrypto, we expect that callbacks are already set, and won't try to
     635             :  * override it.
     636             :  */
     637             : int
     638         110 : pgtls_init(PGconn *conn)
     639             : {
     640             : #ifdef ENABLE_THREAD_SAFETY
     641             : #ifdef WIN32
     642             :     /* Also see similar code in fe-connect.c, default_threadlock() */
     643             :     if (ssl_config_mutex == NULL)
     644             :     {
     645             :         while (InterlockedExchange(&win32_ssl_create_mutex, 1) == 1)
     646             :              /* loop, another thread own the lock */ ;
     647             :         if (ssl_config_mutex == NULL)
     648             :         {
     649             :             if (pthread_mutex_init(&ssl_config_mutex, NULL))
     650             :                 return -1;
     651             :         }
     652             :         InterlockedExchange(&win32_ssl_create_mutex, 0);
     653             :     }
     654             : #endif
     655         110 :     if (pthread_mutex_lock(&ssl_config_mutex))
     656           0 :         return -1;
     657             : 
     658             : #ifdef HAVE_CRYPTO_LOCK
     659             :     if (pq_init_crypto_lib)
     660             :     {
     661             :         /*
     662             :          * If necessary, set up an array to hold locks for libcrypto.
     663             :          * libcrypto will tell us how big to make this array.
     664             :          */
     665             :         if (pq_lockarray == NULL)
     666             :         {
     667             :             int         i;
     668             : 
     669             :             pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
     670             :             if (!pq_lockarray)
     671             :             {
     672             :                 pthread_mutex_unlock(&ssl_config_mutex);
     673             :                 return -1;
     674             :             }
     675             :             for (i = 0; i < CRYPTO_num_locks(); i++)
     676             :             {
     677             :                 if (pthread_mutex_init(&pq_lockarray[i], NULL))
     678             :                 {
     679             :                     free(pq_lockarray);
     680             :                     pq_lockarray = NULL;
     681             :                     pthread_mutex_unlock(&ssl_config_mutex);
     682             :                     return -1;
     683             :                 }
     684             :             }
     685             :         }
     686             : 
     687             :         if (ssl_open_connections++ == 0)
     688             :         {
     689             :             /*
     690             :              * These are only required for threaded libcrypto applications,
     691             :              * but make sure we don't stomp on them if they're already set.
     692             :              */
     693             :             if (CRYPTO_get_id_callback() == NULL)
     694             :                 CRYPTO_set_id_callback(pq_threadidcallback);
     695             :             if (CRYPTO_get_locking_callback() == NULL)
     696             :                 CRYPTO_set_locking_callback(pq_lockingcallback);
     697             :         }
     698             :     }
     699             : #endif                          /* HAVE_CRYPTO_LOCK */
     700             : #endif                          /* ENABLE_THREAD_SAFETY */
     701             : 
     702         110 :     if (!ssl_lib_initialized)
     703             :     {
     704         110 :         if (pq_init_ssl_lib)
     705             :         {
     706             : #ifdef HAVE_OPENSSL_INIT_SSL
     707         110 :             OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
     708             : #else
     709             :             OPENSSL_config(NULL);
     710             :             SSL_library_init();
     711             :             SSL_load_error_strings();
     712             : #endif
     713             :         }
     714         110 :         ssl_lib_initialized = true;
     715             :     }
     716             : 
     717             : #ifdef ENABLE_THREAD_SAFETY
     718         110 :     pthread_mutex_unlock(&ssl_config_mutex);
     719             : #endif
     720         110 :     return 0;
     721             : }
     722             : 
     723             : /*
     724             :  *  This function is needed because if the libpq library is unloaded
     725             :  *  from the application, the callback functions will no longer exist when
     726             :  *  libcrypto is used by other parts of the system.  For this reason,
     727             :  *  we unregister the callback functions when the last libpq
     728             :  *  connection is closed.  (The same would apply for OpenSSL callbacks
     729             :  *  if we had any.)
     730             :  *
     731             :  *  Callbacks are only set when we're compiled in threadsafe mode, so
     732             :  *  we only need to remove them in this case. They are also not needed
     733             :  *  with OpenSSL 1.1.0 anymore.
     734             :  */
     735             : static void
     736         106 : destroy_ssl_system(void)
     737             : {
     738             : #if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK)
     739             :     /* Mutex is created in pgtls_init() */
     740             :     if (pthread_mutex_lock(&ssl_config_mutex))
     741             :         return;
     742             : 
     743             :     if (pq_init_crypto_lib && ssl_open_connections > 0)
     744             :         --ssl_open_connections;
     745             : 
     746             :     if (pq_init_crypto_lib && ssl_open_connections == 0)
     747             :     {
     748             :         /*
     749             :          * No connections left, unregister libcrypto callbacks, if no one
     750             :          * registered different ones in the meantime.
     751             :          */
     752             :         if (CRYPTO_get_locking_callback() == pq_lockingcallback)
     753             :             CRYPTO_set_locking_callback(NULL);
     754             :         if (CRYPTO_get_id_callback() == pq_threadidcallback)
     755             :             CRYPTO_set_id_callback(NULL);
     756             : 
     757             :         /*
     758             :          * We don't free the lock array. If we get another connection in this
     759             :          * process, we will just re-use them with the existing mutexes.
     760             :          *
     761             :          * This means we leak a little memory on repeated load/unload of the
     762             :          * library.
     763             :          */
     764             :     }
     765             : 
     766             :     pthread_mutex_unlock(&ssl_config_mutex);
     767             : #endif
     768         106 : }
     769             : 
     770             : /*
     771             :  *  Create per-connection SSL object, and load the client certificate,
     772             :  *  private key, and trusted CA certs.
     773             :  *
     774             :  *  Returns 0 if OK, -1 on failure (with a message in conn->errorMessage).
     775             :  */
     776             : static int
     777         110 : initialize_SSL(PGconn *conn)
     778             : {
     779             :     SSL_CTX    *SSL_context;
     780             :     struct stat buf;
     781             :     char        homedir[MAXPGPATH];
     782             :     char        fnbuf[MAXPGPATH];
     783             :     char        sebuf[PG_STRERROR_R_BUFLEN];
     784             :     bool        have_homedir;
     785             :     bool        have_cert;
     786             :     bool        have_rootcert;
     787         110 :     EVP_PKEY   *pkey = NULL;
     788             : 
     789             :     /*
     790             :      * We'll need the home directory if any of the relevant parameters are
     791             :      * defaulted.  If pqGetHomeDirectory fails, act as though none of the
     792             :      * files could be found.
     793             :      */
     794         110 :     if (!(conn->sslcert && strlen(conn->sslcert) > 0) ||
     795         110 :         !(conn->sslkey && strlen(conn->sslkey) > 0) ||
     796          30 :         !(conn->sslrootcert && strlen(conn->sslrootcert) > 0) ||
     797          28 :         !(conn->sslcrl && strlen(conn->sslcrl) > 0))
     798         110 :         have_homedir = pqGetHomeDirectory(homedir, sizeof(homedir));
     799             :     else                        /* won't need it */
     800           0 :         have_homedir = false;
     801             : 
     802             :     /*
     803             :      * Create a new SSL_CTX object.
     804             :      *
     805             :      * We used to share a single SSL_CTX between all connections, but it was
     806             :      * complicated if connections used different certificates. So now we
     807             :      * create a separate context for each connection, and accept the overhead.
     808             :      */
     809         110 :     SSL_context = SSL_CTX_new(SSLv23_method());
     810         110 :     if (!SSL_context)
     811             :     {
     812           0 :         char       *err = SSLerrmessage(ERR_get_error());
     813             : 
     814           0 :         printfPQExpBuffer(&conn->errorMessage,
     815           0 :                           libpq_gettext("could not create SSL context: %s\n"),
     816             :                           err);
     817           0 :         SSLerrfree(err);
     818           0 :         return -1;
     819             :     }
     820             : 
     821             :     /*
     822             :      * Delegate the client cert password prompt to the libpq wrapper callback
     823             :      * if any is defined.
     824             :      *
     825             :      * If the application hasn't installed its own and the sslpassword
     826             :      * parameter is non-null, we install ours now to make sure we supply
     827             :      * PGconn->sslpassword to OpenSSL instead of letting it prompt on stdin.
     828             :      *
     829             :      * This will replace OpenSSL's default PEM_def_callback (which prompts on
     830             :      * stdin), but we're only setting it for this SSL context so it's
     831             :      * harmless.
     832             :      */
     833         110 :     if (PQsslKeyPassHook
     834         110 :         || (conn->sslpassword && strlen(conn->sslpassword) > 0))
     835             :     {
     836           6 :         SSL_CTX_set_default_passwd_cb(SSL_context, PQssl_passwd_cb);
     837           6 :         SSL_CTX_set_default_passwd_cb_userdata(SSL_context, conn);
     838             :     }
     839             : 
     840             :     /* Disable old protocol versions */
     841         110 :     SSL_CTX_set_options(SSL_context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
     842             : 
     843             :     /* Set the minimum and maximum protocol versions if necessary */
     844         110 :     if (conn->ssl_min_protocol_version &&
     845           2 :         strlen(conn->ssl_min_protocol_version) != 0)
     846             :     {
     847             :         int         ssl_min_ver;
     848             : 
     849           2 :         ssl_min_ver = ssl_protocol_version_to_openssl(conn->ssl_min_protocol_version);
     850             : 
     851           2 :         if (ssl_min_ver == -1)
     852             :         {
     853           0 :             printfPQExpBuffer(&conn->errorMessage,
     854           0 :                               libpq_gettext("invalid value \"%s\" for minimum version of SSL protocol\n"),
     855             :                               conn->ssl_min_protocol_version);
     856           0 :             SSL_CTX_free(SSL_context);
     857           0 :             return -1;
     858             :         }
     859             : 
     860           2 :         if (!SSL_CTX_set_min_proto_version(SSL_context, ssl_min_ver))
     861             :         {
     862           0 :             char       *err = SSLerrmessage(ERR_get_error());
     863             : 
     864           0 :             printfPQExpBuffer(&conn->errorMessage,
     865           0 :                               libpq_gettext("could not set minimum version of SSL protocol: %s\n"),
     866             :                               err);
     867           0 :             SSLerrfree(err);
     868           0 :             SSL_CTX_free(SSL_context);
     869           0 :             return -1;
     870             :         }
     871             :     }
     872             : 
     873         110 :     if (conn->ssl_max_protocol_version &&
     874           2 :         strlen(conn->ssl_max_protocol_version) != 0)
     875             :     {
     876             :         int         ssl_max_ver;
     877             : 
     878           2 :         ssl_max_ver = ssl_protocol_version_to_openssl(conn->ssl_max_protocol_version);
     879             : 
     880           2 :         if (ssl_max_ver == -1)
     881             :         {
     882           0 :             printfPQExpBuffer(&conn->errorMessage,
     883           0 :                               libpq_gettext("invalid value \"%s\" for maximum version of SSL protocol\n"),
     884             :                               conn->ssl_max_protocol_version);
     885           0 :             SSL_CTX_free(SSL_context);
     886           0 :             return -1;
     887             :         }
     888             : 
     889           2 :         if (!SSL_CTX_set_max_proto_version(SSL_context, ssl_max_ver))
     890             :         {
     891           0 :             char       *err = SSLerrmessage(ERR_get_error());
     892             : 
     893           0 :             printfPQExpBuffer(&conn->errorMessage,
     894           0 :                               libpq_gettext("could not set maximum version of SSL protocol: %s\n"),
     895             :                               err);
     896           0 :             SSLerrfree(err);
     897           0 :             SSL_CTX_free(SSL_context);
     898           0 :             return -1;
     899             :         }
     900             :     }
     901             : 
     902             :     /*
     903             :      * Disable OpenSSL's moving-write-buffer sanity check, because it causes
     904             :      * unnecessary failures in nonblocking send cases.
     905             :      */
     906         110 :     SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
     907             : 
     908             :     /*
     909             :      * If the root cert file exists, load it so we can perform certificate
     910             :      * verification. If sslmode is "verify-full" we will also do further
     911             :      * verification after the connection has been completed.
     912             :      */
     913         110 :     if (conn->sslrootcert && strlen(conn->sslrootcert) > 0)
     914         108 :         strlcpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
     915           2 :     else if (have_homedir)
     916           2 :         snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
     917             :     else
     918           0 :         fnbuf[0] = '\0';
     919             : 
     920         220 :     if (fnbuf[0] != '\0' &&
     921         110 :         stat(fnbuf, &buf) == 0)
     922          92 :     {
     923             :         X509_STORE *cvstore;
     924             : 
     925          92 :         if (SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL) != 1)
     926             :         {
     927           0 :             char       *err = SSLerrmessage(ERR_get_error());
     928             : 
     929           0 :             printfPQExpBuffer(&conn->errorMessage,
     930           0 :                               libpq_gettext("could not read root certificate file \"%s\": %s\n"),
     931             :                               fnbuf, err);
     932           0 :             SSLerrfree(err);
     933           0 :             SSL_CTX_free(SSL_context);
     934           0 :             return -1;
     935             :         }
     936             : 
     937          92 :         if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
     938             :         {
     939          92 :             if (conn->sslcrl && strlen(conn->sslcrl) > 0)
     940           8 :                 strlcpy(fnbuf, conn->sslcrl, sizeof(fnbuf));
     941          84 :             else if (have_homedir)
     942          84 :                 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE);
     943             :             else
     944           0 :                 fnbuf[0] = '\0';
     945             : 
     946             :             /* Set the flags to check against the complete CRL chain */
     947         184 :             if (fnbuf[0] != '\0' &&
     948          92 :                 X509_STORE_load_locations(cvstore, fnbuf, NULL) == 1)
     949             :             {
     950           6 :                 X509_STORE_set_flags(cvstore,
     951             :                                      X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
     952             :             }
     953             :             /* if not found, silently ignore;  we do not require CRL */
     954          92 :             ERR_clear_error();
     955             :         }
     956          92 :         have_rootcert = true;
     957             :     }
     958             :     else
     959             :     {
     960             :         /*
     961             :          * stat() failed; assume root file doesn't exist.  If sslmode is
     962             :          * verify-ca or verify-full, this is an error.  Otherwise, continue
     963             :          * without performing any server cert verification.
     964             :          */
     965          18 :         if (conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */
     966             :         {
     967             :             /*
     968             :              * The only way to reach here with an empty filename is if
     969             :              * pqGetHomeDirectory failed.  That's a sufficiently unusual case
     970             :              * that it seems worth having a specialized error message for it.
     971             :              */
     972           4 :             if (fnbuf[0] == '\0')
     973           0 :                 printfPQExpBuffer(&conn->errorMessage,
     974           0 :                                   libpq_gettext("could not get home directory to locate root certificate file\n"
     975             :                                                 "Either provide the file or change sslmode to disable server certificate verification.\n"));
     976             :             else
     977           4 :                 printfPQExpBuffer(&conn->errorMessage,
     978           4 :                                   libpq_gettext("root certificate file \"%s\" does not exist\n"
     979             :                                                 "Either provide the file or change sslmode to disable server certificate verification.\n"), fnbuf);
     980           4 :             SSL_CTX_free(SSL_context);
     981           4 :             return -1;
     982             :         }
     983          14 :         have_rootcert = false;
     984             :     }
     985             : 
     986             :     /* Read the client certificate file */
     987         106 :     if (conn->sslcert && strlen(conn->sslcert) > 0)
     988         106 :         strlcpy(fnbuf, conn->sslcert, sizeof(fnbuf));
     989           0 :     else if (have_homedir)
     990           0 :         snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
     991             :     else
     992           0 :         fnbuf[0] = '\0';
     993             : 
     994         106 :     if (fnbuf[0] == '\0')
     995             :     {
     996             :         /* no home directory, proceed without a client cert */
     997           0 :         have_cert = false;
     998             :     }
     999         106 :     else if (stat(fnbuf, &buf) != 0)
    1000             :     {
    1001             :         /*
    1002             :          * If file is not present, just go on without a client cert; server
    1003             :          * might or might not accept the connection.  Any other error,
    1004             :          * however, is grounds for complaint.
    1005             :          */
    1006          76 :         if (errno != ENOENT && errno != ENOTDIR)
    1007             :         {
    1008           0 :             printfPQExpBuffer(&conn->errorMessage,
    1009           0 :                               libpq_gettext("could not open certificate file \"%s\": %s\n"),
    1010           0 :                               fnbuf, strerror_r(errno, sebuf, sizeof(sebuf)));
    1011           0 :             SSL_CTX_free(SSL_context);
    1012           0 :             return -1;
    1013             :         }
    1014          76 :         have_cert = false;
    1015             :     }
    1016             :     else
    1017             :     {
    1018             :         /*
    1019             :          * Cert file exists, so load it. Since OpenSSL doesn't provide the
    1020             :          * equivalent of "SSL_use_certificate_chain_file", we have to load it
    1021             :          * into the SSL context, rather than the SSL object.
    1022             :          */
    1023          30 :         if (SSL_CTX_use_certificate_chain_file(SSL_context, fnbuf) != 1)
    1024             :         {
    1025           0 :             char       *err = SSLerrmessage(ERR_get_error());
    1026             : 
    1027           0 :             printfPQExpBuffer(&conn->errorMessage,
    1028           0 :                               libpq_gettext("could not read certificate file \"%s\": %s\n"),
    1029             :                               fnbuf, err);
    1030           0 :             SSLerrfree(err);
    1031           0 :             SSL_CTX_free(SSL_context);
    1032           0 :             return -1;
    1033             :         }
    1034             : 
    1035             :         /* need to load the associated private key, too */
    1036          30 :         have_cert = true;
    1037             :     }
    1038             : 
    1039             :     /*
    1040             :      * The SSL context is now loaded with the correct root and client
    1041             :      * certificates. Create a connection-specific SSL object. The private key
    1042             :      * is loaded directly into the SSL object. (We could load the private key
    1043             :      * into the context, too, but we have done it this way historically, and
    1044             :      * it doesn't really matter.)
    1045             :      */
    1046         212 :     if (!(conn->ssl = SSL_new(SSL_context)) ||
    1047         212 :         !SSL_set_app_data(conn->ssl, conn) ||
    1048         106 :         !my_SSL_set_fd(conn, conn->sock))
    1049             :     {
    1050           0 :         char       *err = SSLerrmessage(ERR_get_error());
    1051             : 
    1052           0 :         printfPQExpBuffer(&conn->errorMessage,
    1053           0 :                           libpq_gettext("could not establish SSL connection: %s\n"),
    1054             :                           err);
    1055           0 :         SSLerrfree(err);
    1056           0 :         SSL_CTX_free(SSL_context);
    1057           0 :         return -1;
    1058             :     }
    1059         106 :     conn->ssl_in_use = true;
    1060             : 
    1061             :     /*
    1062             :      * SSL contexts are reference counted by OpenSSL. We can free it as soon
    1063             :      * as we have created the SSL object, and it will stick around for as long
    1064             :      * as it's actually needed.
    1065             :      */
    1066         106 :     SSL_CTX_free(SSL_context);
    1067         106 :     SSL_context = NULL;
    1068             : 
    1069             :     /*
    1070             :      * Read the SSL key. If a key is specified, treat it as an engine:key
    1071             :      * combination if there is colon present - we don't support files with
    1072             :      * colon in the name. The exception is if the second character is a colon,
    1073             :      * in which case it can be a Windows filename with drive specification.
    1074             :      */
    1075         106 :     if (have_cert && conn->sslkey && strlen(conn->sslkey) > 0)
    1076             :     {
    1077             : #ifdef USE_SSL_ENGINE
    1078          60 :         if (strchr(conn->sslkey, ':')
    1079             : #ifdef WIN32
    1080             :             && conn->sslkey[1] != ':'
    1081             : #endif
    1082             :             )
    1083             :         {
    1084             :             /* Colon, but not in second character, treat as engine:key */
    1085           0 :             char       *engine_str = strdup(conn->sslkey);
    1086             :             char       *engine_colon;
    1087             : 
    1088           0 :             if (engine_str == NULL)
    1089             :             {
    1090           0 :                 printfPQExpBuffer(&conn->errorMessage,
    1091           0 :                                   libpq_gettext("out of memory\n"));
    1092           0 :                 return -1;
    1093             :             }
    1094             : 
    1095             :             /* cannot return NULL because we already checked before strdup */
    1096           0 :             engine_colon = strchr(engine_str, ':');
    1097             : 
    1098           0 :             *engine_colon = '\0';   /* engine_str now has engine name */
    1099           0 :             engine_colon++;     /* engine_colon now has key name */
    1100             : 
    1101           0 :             conn->engine = ENGINE_by_id(engine_str);
    1102           0 :             if (conn->engine == NULL)
    1103             :             {
    1104           0 :                 char       *err = SSLerrmessage(ERR_get_error());
    1105             : 
    1106           0 :                 printfPQExpBuffer(&conn->errorMessage,
    1107           0 :                                   libpq_gettext("could not load SSL engine \"%s\": %s\n"),
    1108             :                                   engine_str, err);
    1109           0 :                 SSLerrfree(err);
    1110           0 :                 free(engine_str);
    1111           0 :                 return -1;
    1112             :             }
    1113             : 
    1114           0 :             if (ENGINE_init(conn->engine) == 0)
    1115             :             {
    1116           0 :                 char       *err = SSLerrmessage(ERR_get_error());
    1117             : 
    1118           0 :                 printfPQExpBuffer(&conn->errorMessage,
    1119           0 :                                   libpq_gettext("could not initialize SSL engine \"%s\": %s\n"),
    1120             :                                   engine_str, err);
    1121           0 :                 SSLerrfree(err);
    1122           0 :                 ENGINE_free(conn->engine);
    1123           0 :                 conn->engine = NULL;
    1124           0 :                 free(engine_str);
    1125           0 :                 return -1;
    1126             :             }
    1127             : 
    1128           0 :             pkey = ENGINE_load_private_key(conn->engine, engine_colon,
    1129             :                                            NULL, NULL);
    1130           0 :             if (pkey == NULL)
    1131             :             {
    1132           0 :                 char       *err = SSLerrmessage(ERR_get_error());
    1133             : 
    1134           0 :                 printfPQExpBuffer(&conn->errorMessage,
    1135           0 :                                   libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"),
    1136             :                                   engine_colon, engine_str, err);
    1137           0 :                 SSLerrfree(err);
    1138           0 :                 ENGINE_finish(conn->engine);
    1139           0 :                 ENGINE_free(conn->engine);
    1140           0 :                 conn->engine = NULL;
    1141           0 :                 free(engine_str);
    1142           0 :                 return -1;
    1143             :             }
    1144           0 :             if (SSL_use_PrivateKey(conn->ssl, pkey) != 1)
    1145             :             {
    1146           0 :                 char       *err = SSLerrmessage(ERR_get_error());
    1147             : 
    1148           0 :                 printfPQExpBuffer(&conn->errorMessage,
    1149           0 :                                   libpq_gettext("could not load private SSL key \"%s\" from engine \"%s\": %s\n"),
    1150             :                                   engine_colon, engine_str, err);
    1151           0 :                 SSLerrfree(err);
    1152           0 :                 ENGINE_finish(conn->engine);
    1153           0 :                 ENGINE_free(conn->engine);
    1154           0 :                 conn->engine = NULL;
    1155           0 :                 free(engine_str);
    1156           0 :                 return -1;
    1157             :             }
    1158             : 
    1159           0 :             free(engine_str);
    1160             : 
    1161           0 :             fnbuf[0] = '\0';    /* indicate we're not going to load from a
    1162             :                                  * file */
    1163             :         }
    1164             :         else
    1165             : #endif                          /* USE_SSL_ENGINE */
    1166             :         {
    1167             :             /* PGSSLKEY is not an engine, treat it as a filename */
    1168          30 :             strlcpy(fnbuf, conn->sslkey, sizeof(fnbuf));
    1169             :         }
    1170             :     }
    1171          76 :     else if (have_homedir)
    1172             :     {
    1173             :         /* No PGSSLKEY specified, load default file */
    1174          76 :         snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
    1175             :     }
    1176             :     else
    1177           0 :         fnbuf[0] = '\0';
    1178             : 
    1179         106 :     if (have_cert && fnbuf[0] != '\0')
    1180             :     {
    1181             :         /* read the client key from file */
    1182             : 
    1183          30 :         if (stat(fnbuf, &buf) != 0)
    1184             :         {
    1185           0 :             printfPQExpBuffer(&conn->errorMessage,
    1186           0 :                               libpq_gettext("certificate present, but not private key file \"%s\"\n"),
    1187             :                               fnbuf);
    1188           0 :             return -1;
    1189             :         }
    1190             : #ifndef WIN32
    1191          30 :         if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
    1192             :         {
    1193           2 :             printfPQExpBuffer(&conn->errorMessage,
    1194           2 :                               libpq_gettext("private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
    1195             :                               fnbuf);
    1196           2 :             return -1;
    1197             :         }
    1198             : #endif
    1199             : 
    1200          28 :         if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_PEM) != 1)
    1201             :         {
    1202           6 :             char       *err = SSLerrmessage(ERR_get_error());
    1203             : 
    1204             :             /*
    1205             :              * We'll try to load the file in DER (binary ASN.1) format, and if
    1206             :              * that fails too, report the original error. This could mask
    1207             :              * issues where there's something wrong with a DER-format cert,
    1208             :              * but we'd have to duplicate openssl's format detection to be
    1209             :              * smarter than this. We can't just probe for a leading -----BEGIN
    1210             :              * because PEM can have leading non-matching lines and blanks.
    1211             :              * OpenSSL doesn't expose its get_name(...) and its PEM routines
    1212             :              * don't differentiate between failure modes in enough detail to
    1213             :              * let us tell the difference between "not PEM, try DER" and
    1214             :              * "wrong password".
    1215             :              */
    1216           6 :             if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_ASN1) != 1)
    1217             :             {
    1218           2 :                 printfPQExpBuffer(&conn->errorMessage,
    1219           2 :                                   libpq_gettext("could not load private key file \"%s\": %s\n"),
    1220             :                                   fnbuf, err);
    1221           2 :                 SSLerrfree(err);
    1222           2 :                 return -1;
    1223             :             }
    1224             : 
    1225           4 :             SSLerrfree(err);
    1226             : 
    1227             :         }
    1228             :     }
    1229             : 
    1230             :     /* verify that the cert and key go together */
    1231         128 :     if (have_cert &&
    1232          26 :         SSL_check_private_key(conn->ssl) != 1)
    1233             :     {
    1234           0 :         char       *err = SSLerrmessage(ERR_get_error());
    1235             : 
    1236           0 :         printfPQExpBuffer(&conn->errorMessage,
    1237           0 :                           libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
    1238             :                           fnbuf, err);
    1239           0 :         SSLerrfree(err);
    1240           0 :         return -1;
    1241             :     }
    1242             : 
    1243             :     /*
    1244             :      * If a root cert was loaded, also set our certificate verification
    1245             :      * callback.
    1246             :      */
    1247         102 :     if (have_rootcert)
    1248          88 :         SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, verify_cb);
    1249             : 
    1250             :     /*
    1251             :      * Set compression option if necessary.
    1252             :      */
    1253         102 :     if (conn->sslcompression && conn->sslcompression[0] == '0')
    1254         102 :         SSL_set_options(conn->ssl, SSL_OP_NO_COMPRESSION);
    1255             :     else
    1256           0 :         SSL_clear_options(conn->ssl, SSL_OP_NO_COMPRESSION);
    1257             : 
    1258         102 :     return 0;
    1259             : }
    1260             : 
    1261             : /*
    1262             :  *  Attempt to negotiate SSL connection.
    1263             :  */
    1264             : static PostgresPollingStatusType
    1265         306 : open_client_SSL(PGconn *conn)
    1266             : {
    1267             :     int         r;
    1268             : 
    1269         306 :     ERR_clear_error();
    1270         306 :     r = SSL_connect(conn->ssl);
    1271         306 :     if (r <= 0)
    1272             :     {
    1273         216 :         int         err = SSL_get_error(conn->ssl, r);
    1274             :         unsigned long ecode;
    1275             : 
    1276         216 :         ecode = ERR_get_error();
    1277         216 :         switch (err)
    1278             :         {
    1279         204 :             case SSL_ERROR_WANT_READ:
    1280         204 :                 return PGRES_POLLING_READING;
    1281             : 
    1282           0 :             case SSL_ERROR_WANT_WRITE:
    1283           0 :                 return PGRES_POLLING_WRITING;
    1284             : 
    1285           0 :             case SSL_ERROR_SYSCALL:
    1286             :                 {
    1287             :                     char        sebuf[PG_STRERROR_R_BUFLEN];
    1288             : 
    1289           0 :                     if (r == -1)
    1290           0 :                         printfPQExpBuffer(&conn->errorMessage,
    1291           0 :                                           libpq_gettext("SSL SYSCALL error: %s\n"),
    1292           0 :                                           SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
    1293             :                     else
    1294           0 :                         printfPQExpBuffer(&conn->errorMessage,
    1295           0 :                                           libpq_gettext("SSL SYSCALL error: EOF detected\n"));
    1296           0 :                     pgtls_close(conn);
    1297           0 :                     return PGRES_POLLING_FAILED;
    1298             :                 }
    1299          12 :             case SSL_ERROR_SSL:
    1300             :                 {
    1301          12 :                     char       *err = SSLerrmessage(ecode);
    1302             : 
    1303          12 :                     printfPQExpBuffer(&conn->errorMessage,
    1304          12 :                                       libpq_gettext("SSL error: %s\n"),
    1305             :                                       err);
    1306          12 :                     SSLerrfree(err);
    1307          12 :                     pgtls_close(conn);
    1308          12 :                     return PGRES_POLLING_FAILED;
    1309             :                 }
    1310             : 
    1311           0 :             default:
    1312           0 :                 printfPQExpBuffer(&conn->errorMessage,
    1313           0 :                                   libpq_gettext("unrecognized SSL error code: %d\n"),
    1314             :                                   err);
    1315           0 :                 pgtls_close(conn);
    1316           0 :                 return PGRES_POLLING_FAILED;
    1317             :         }
    1318             :     }
    1319             : 
    1320             :     /*
    1321             :      * We already checked the server certificate in initialize_SSL() using
    1322             :      * SSL_CTX_set_verify(), if root.crt exists.
    1323             :      */
    1324             : 
    1325             :     /* get server certificate */
    1326          90 :     conn->peer = SSL_get_peer_certificate(conn->ssl);
    1327          90 :     if (conn->peer == NULL)
    1328             :     {
    1329           0 :         char       *err = SSLerrmessage(ERR_get_error());
    1330             : 
    1331           0 :         printfPQExpBuffer(&conn->errorMessage,
    1332           0 :                           libpq_gettext("certificate could not be obtained: %s\n"),
    1333             :                           err);
    1334           0 :         SSLerrfree(err);
    1335           0 :         pgtls_close(conn);
    1336           0 :         return PGRES_POLLING_FAILED;
    1337             :     }
    1338             : 
    1339          90 :     if (!pq_verify_peer_name_matches_certificate(conn))
    1340             :     {
    1341          14 :         pgtls_close(conn);
    1342          14 :         return PGRES_POLLING_FAILED;
    1343             :     }
    1344             : 
    1345             :     /* SSL handshake is complete */
    1346          76 :     return PGRES_POLLING_OK;
    1347             : }
    1348             : 
    1349             : void
    1350         110 : pgtls_close(PGconn *conn)
    1351             : {
    1352         110 :     bool        destroy_needed = false;
    1353             : 
    1354         110 :     if (conn->ssl)
    1355             :     {
    1356             :         /*
    1357             :          * We can't destroy everything SSL-related here due to the possible
    1358             :          * later calls to OpenSSL routines which may need our thread
    1359             :          * callbacks, so set a flag here and check at the end.
    1360             :          */
    1361         106 :         destroy_needed = true;
    1362             : 
    1363         106 :         SSL_shutdown(conn->ssl);
    1364         106 :         SSL_free(conn->ssl);
    1365         106 :         conn->ssl = NULL;
    1366         106 :         conn->ssl_in_use = false;
    1367             :     }
    1368             : 
    1369         110 :     if (conn->peer)
    1370             :     {
    1371          90 :         X509_free(conn->peer);
    1372          90 :         conn->peer = NULL;
    1373             :     }
    1374             : 
    1375             : #ifdef USE_SSL_ENGINE
    1376         110 :     if (conn->engine)
    1377             :     {
    1378           0 :         ENGINE_finish(conn->engine);
    1379           0 :         ENGINE_free(conn->engine);
    1380           0 :         conn->engine = NULL;
    1381             :     }
    1382             : #endif
    1383             : 
    1384             :     /*
    1385             :      * This will remove our SSL locking hooks, if this is the last SSL
    1386             :      * connection, which means we must wait to call it until after all SSL
    1387             :      * calls have been made, otherwise we can end up with a race condition and
    1388             :      * possible deadlocks.
    1389             :      *
    1390             :      * See comments above destroy_ssl_system().
    1391             :      */
    1392         110 :     if (destroy_needed)
    1393         106 :         destroy_ssl_system();
    1394         110 : }
    1395             : 
    1396             : 
    1397             : /*
    1398             :  * Obtain reason string for passed SSL errcode
    1399             :  *
    1400             :  * ERR_get_error() is used by caller to get errcode to pass here.
    1401             :  *
    1402             :  * Some caution is needed here since ERR_reason_error_string will
    1403             :  * return NULL if it doesn't recognize the error code.  We don't
    1404             :  * want to return NULL ever.
    1405             :  */
    1406             : static char ssl_nomem[] = "out of memory allocating error description";
    1407             : 
    1408             : #define SSL_ERR_LEN 128
    1409             : 
    1410             : static char *
    1411          22 : SSLerrmessage(unsigned long ecode)
    1412             : {
    1413             :     const char *errreason;
    1414             :     char       *errbuf;
    1415             : 
    1416          22 :     errbuf = malloc(SSL_ERR_LEN);
    1417          22 :     if (!errbuf)
    1418           0 :         return ssl_nomem;
    1419          22 :     if (ecode == 0)
    1420             :     {
    1421           0 :         snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("no SSL error reported"));
    1422           0 :         return errbuf;
    1423             :     }
    1424          22 :     errreason = ERR_reason_error_string(ecode);
    1425          22 :     if (errreason != NULL)
    1426             :     {
    1427          22 :         strlcpy(errbuf, errreason, SSL_ERR_LEN);
    1428          22 :         return errbuf;
    1429             :     }
    1430           0 :     snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("SSL error code %lu"), ecode);
    1431           0 :     return errbuf;
    1432             : }
    1433             : 
    1434             : static void
    1435          22 : SSLerrfree(char *buf)
    1436             : {
    1437          22 :     if (buf != ssl_nomem)
    1438          22 :         free(buf);
    1439          22 : }
    1440             : 
    1441             : /* ------------------------------------------------------------ */
    1442             : /*                  SSL information functions                   */
    1443             : /* ------------------------------------------------------------ */
    1444             : 
    1445             : /*
    1446             :  *  Return pointer to OpenSSL object.
    1447             :  */
    1448             : void *
    1449           0 : PQgetssl(PGconn *conn)
    1450             : {
    1451           0 :     if (!conn)
    1452           0 :         return NULL;
    1453           0 :     return conn->ssl;
    1454             : }
    1455             : 
    1456             : void *
    1457           0 : PQsslStruct(PGconn *conn, const char *struct_name)
    1458             : {
    1459           0 :     if (!conn)
    1460           0 :         return NULL;
    1461           0 :     if (strcmp(struct_name, "OpenSSL") == 0)
    1462           0 :         return conn->ssl;
    1463           0 :     return NULL;
    1464             : }
    1465             : 
    1466             : const char *const *
    1467           0 : PQsslAttributeNames(PGconn *conn)
    1468             : {
    1469             :     static const char *const result[] = {
    1470             :         "library",
    1471             :         "key_bits",
    1472             :         "cipher",
    1473             :         "compression",
    1474             :         "protocol",
    1475             :         NULL
    1476             :     };
    1477             : 
    1478           0 :     return result;
    1479             : }
    1480             : 
    1481             : const char *
    1482           0 : PQsslAttribute(PGconn *conn, const char *attribute_name)
    1483             : {
    1484           0 :     if (!conn)
    1485           0 :         return NULL;
    1486           0 :     if (conn->ssl == NULL)
    1487           0 :         return NULL;
    1488             : 
    1489           0 :     if (strcmp(attribute_name, "library") == 0)
    1490           0 :         return "OpenSSL";
    1491             : 
    1492           0 :     if (strcmp(attribute_name, "key_bits") == 0)
    1493             :     {
    1494             :         static char sslbits_str[12];
    1495             :         int         sslbits;
    1496             : 
    1497           0 :         SSL_get_cipher_bits(conn->ssl, &sslbits);
    1498           0 :         snprintf(sslbits_str, sizeof(sslbits_str), "%d", sslbits);
    1499           0 :         return sslbits_str;
    1500             :     }
    1501             : 
    1502           0 :     if (strcmp(attribute_name, "cipher") == 0)
    1503           0 :         return SSL_get_cipher(conn->ssl);
    1504             : 
    1505           0 :     if (strcmp(attribute_name, "compression") == 0)
    1506           0 :         return SSL_get_current_compression(conn->ssl) ? "on" : "off";
    1507             : 
    1508           0 :     if (strcmp(attribute_name, "protocol") == 0)
    1509           0 :         return SSL_get_version(conn->ssl);
    1510             : 
    1511           0 :     return NULL;                /* unknown attribute */
    1512             : }
    1513             : 
    1514             : /*
    1515             :  * Private substitute BIO: this does the sending and receiving using
    1516             :  * pqsecure_raw_write() and pqsecure_raw_read() instead, to allow those
    1517             :  * functions to disable SIGPIPE and give better error messages on I/O errors.
    1518             :  *
    1519             :  * These functions are closely modelled on the standard socket BIO in OpenSSL;
    1520             :  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
    1521             :  * XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons
    1522             :  * to retry; do we need to adopt their logic for that?
    1523             :  */
    1524             : 
    1525             : #ifndef HAVE_BIO_GET_DATA
    1526             : #define BIO_get_data(bio) (bio->ptr)
    1527             : #define BIO_set_data(bio, data) (bio->ptr = data)
    1528             : #endif
    1529             : 
    1530             : static BIO_METHOD *my_bio_methods;
    1531             : 
    1532             : static int
    1533        2528 : my_sock_read(BIO *h, char *buf, int size)
    1534             : {
    1535             :     int         res;
    1536             : 
    1537        2528 :     res = pqsecure_raw_read((PGconn *) BIO_get_data(h), buf, size);
    1538        2528 :     BIO_clear_retry_flags(h);
    1539        2528 :     if (res < 0)
    1540             :     {
    1541             :         /* If we were interrupted, tell caller to retry */
    1542         368 :         switch (SOCK_ERRNO)
    1543             :         {
    1544             : #ifdef EAGAIN
    1545         368 :             case EAGAIN:
    1546             : #endif
    1547             : #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
    1548             :             case EWOULDBLOCK:
    1549             : #endif
    1550             :             case EINTR:
    1551         368 :                 BIO_set_retry_read(h);
    1552         368 :                 break;
    1553             : 
    1554           0 :             default:
    1555           0 :                 break;
    1556             :         }
    1557        2160 :     }
    1558             : 
    1559        2528 :     return res;
    1560             : }
    1561             : 
    1562             : static int
    1563         602 : my_sock_write(BIO *h, const char *buf, int size)
    1564             : {
    1565             :     int         res;
    1566             : 
    1567         602 :     res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
    1568         602 :     BIO_clear_retry_flags(h);
    1569         602 :     if (res <= 0)
    1570             :     {
    1571             :         /* If we were interrupted, tell caller to retry */
    1572           0 :         switch (SOCK_ERRNO)
    1573             :         {
    1574             : #ifdef EAGAIN
    1575           0 :             case EAGAIN:
    1576             : #endif
    1577             : #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
    1578             :             case EWOULDBLOCK:
    1579             : #endif
    1580             :             case EINTR:
    1581           0 :                 BIO_set_retry_write(h);
    1582           0 :                 break;
    1583             : 
    1584           0 :             default:
    1585           0 :                 break;
    1586             :         }
    1587         602 :     }
    1588             : 
    1589         602 :     return res;
    1590             : }
    1591             : 
    1592             : static BIO_METHOD *
    1593         106 : my_BIO_s_socket(void)
    1594             : {
    1595         106 :     if (!my_bio_methods)
    1596             :     {
    1597         106 :         BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
    1598             : #ifdef HAVE_BIO_METH_NEW
    1599             :         int         my_bio_index;
    1600             : 
    1601         106 :         my_bio_index = BIO_get_new_index();
    1602         106 :         if (my_bio_index == -1)
    1603           0 :             return NULL;
    1604         106 :         my_bio_methods = BIO_meth_new(my_bio_index, "libpq socket");
    1605         106 :         if (!my_bio_methods)
    1606           0 :             return NULL;
    1607             : 
    1608             :         /*
    1609             :          * As of this writing, these functions never fail. But check anyway,
    1610             :          * like OpenSSL's own examples do.
    1611             :          */
    1612         212 :         if (!BIO_meth_set_write(my_bio_methods, my_sock_write) ||
    1613         212 :             !BIO_meth_set_read(my_bio_methods, my_sock_read) ||
    1614         212 :             !BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) ||
    1615         212 :             !BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) ||
    1616         212 :             !BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) ||
    1617         212 :             !BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) ||
    1618         212 :             !BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) ||
    1619         106 :             !BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom)))
    1620             :         {
    1621           0 :             BIO_meth_free(my_bio_methods);
    1622           0 :             my_bio_methods = NULL;
    1623           0 :             return NULL;
    1624             :         }
    1625             : #else
    1626             :         my_bio_methods = malloc(sizeof(BIO_METHOD));
    1627             :         if (!my_bio_methods)
    1628             :             return NULL;
    1629             :         memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
    1630             :         my_bio_methods->bread = my_sock_read;
    1631             :         my_bio_methods->bwrite = my_sock_write;
    1632             : #endif
    1633             :     }
    1634         106 :     return my_bio_methods;
    1635             : }
    1636             : 
    1637             : /* This should exactly match OpenSSL's SSL_set_fd except for using my BIO */
    1638             : static int
    1639         106 : my_SSL_set_fd(PGconn *conn, int fd)
    1640             : {
    1641         106 :     int         ret = 0;
    1642             :     BIO        *bio;
    1643             :     BIO_METHOD *bio_method;
    1644             : 
    1645         106 :     bio_method = my_BIO_s_socket();
    1646         106 :     if (bio_method == NULL)
    1647             :     {
    1648           0 :         SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
    1649           0 :         goto err;
    1650             :     }
    1651         106 :     bio = BIO_new(bio_method);
    1652         106 :     if (bio == NULL)
    1653             :     {
    1654           0 :         SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
    1655           0 :         goto err;
    1656             :     }
    1657         106 :     BIO_set_data(bio, conn);
    1658             : 
    1659         106 :     SSL_set_bio(conn->ssl, bio, bio);
    1660         106 :     BIO_set_fd(bio, fd, BIO_NOCLOSE);
    1661         106 :     ret = 1;
    1662         106 : err:
    1663         106 :     return ret;
    1664             : }
    1665             : 
    1666             : /*
    1667             :  * This is the default handler to return a client cert password from
    1668             :  * conn->sslpassword. Apps may install it explicitly if they want to
    1669             :  * prevent openssl from ever prompting on stdin.
    1670             :  */
    1671             : int
    1672           4 : PQdefaultSSLKeyPassHook_OpenSSL(char *buf, int size, PGconn *conn)
    1673             : {
    1674           4 :     if (conn->sslpassword)
    1675             :     {
    1676           4 :         if (strlen(conn->sslpassword) + 1 > size)
    1677           0 :             fprintf(stderr, libpq_gettext("WARNING: sslpassword truncated\n"));
    1678           4 :         strncpy(buf, conn->sslpassword, size);
    1679           4 :         buf[size - 1] = '\0';
    1680           4 :         return strlen(buf);
    1681             :     }
    1682             :     else
    1683             :     {
    1684           0 :         buf[0] = '\0';
    1685           0 :         return 0;
    1686             :     }
    1687             : }
    1688             : 
    1689             : PQsslKeyPassHook_OpenSSL_type
    1690           0 : PQgetSSLKeyPassHook_OpenSSL(void)
    1691             : {
    1692           0 :     return PQsslKeyPassHook;
    1693             : }
    1694             : 
    1695             : void
    1696           0 : PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook)
    1697             : {
    1698           0 :     PQsslKeyPassHook = hook;
    1699           0 : }
    1700             : 
    1701             : /*
    1702             :  * Supply a password to decrypt a client certificate.
    1703             :  *
    1704             :  * This must match OpenSSL type pem_password_cb.
    1705             :  */
    1706             : static int
    1707           4 : PQssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
    1708             : {
    1709           4 :     PGconn     *conn = userdata;
    1710             : 
    1711           4 :     if (PQsslKeyPassHook)
    1712           0 :         return PQsslKeyPassHook(buf, size, conn);
    1713             :     else
    1714           4 :         return PQdefaultSSLKeyPassHook_OpenSSL(buf, size, conn);
    1715             : }
    1716             : 
    1717             : /*
    1718             :  * Convert TLS protocol version string to OpenSSL values
    1719             :  *
    1720             :  * If a version is passed that is not supported by the current OpenSSL version,
    1721             :  * then we return -1. If a non-negative value is returned, subsequent code can
    1722             :  * assume it is working with a supported version.
    1723             :  *
    1724             :  * Note: this is rather similar to the backend routine in be-secure-openssl.c,
    1725             :  * so make sure to update both routines if changing this one.
    1726             :  */
    1727             : static int
    1728           4 : ssl_protocol_version_to_openssl(const char *protocol)
    1729             : {
    1730           4 :     if (pg_strcasecmp("TLSv1", protocol) == 0)
    1731           0 :         return TLS1_VERSION;
    1732             : 
    1733             : #ifdef TLS1_1_VERSION
    1734           4 :     if (pg_strcasecmp("TLSv1.1", protocol) == 0)
    1735           0 :         return TLS1_1_VERSION;
    1736             : #endif
    1737             : 
    1738             : #ifdef TLS1_2_VERSION
    1739           4 :     if (pg_strcasecmp("TLSv1.2", protocol) == 0)
    1740           4 :         return TLS1_2_VERSION;
    1741             : #endif
    1742             : 
    1743             : #ifdef TLS1_3_VERSION
    1744           0 :     if (pg_strcasecmp("TLSv1.3", protocol) == 0)
    1745           0 :         return TLS1_3_VERSION;
    1746             : #endif
    1747             : 
    1748           0 :     return -1;
    1749             : }

Generated by: LCOV version 1.13