PostgreSQL Source Code  git master
fe-secure-openssl.c File Reference
#include "postgres_fe.h"
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include "libpq-fe.h"
#include "fe-auth.h"
#include "fe-secure-common.h"
#include "libpq-int.h"
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <openssl/ssl.h>
#include <openssl/conf.h>
#include <openssl/x509v3.h>
Include dependency graph for fe-secure-openssl.c:

Go to the source code of this file.

Macros

#define SSL_ERR_LEN   128
 
#define BIO_get_data(bio)   (bio->ptr)
 
#define BIO_set_data(bio, data)   (bio->ptr = data)
 

Functions

static int verify_cb (int ok, X509_STORE_CTX *ctx)
 
static int openssl_verify_peer_name_matches_certificate_name (PGconn *conn, ASN1_STRING *name, char **store_name)
 
static void destroy_ssl_system (void)
 
static int initialize_SSL (PGconn *conn)
 
static PostgresPollingStatusType open_client_SSL (PGconn *)
 
static char * SSLerrmessage (unsigned long ecode)
 
static void SSLerrfree (char *buf)
 
static int my_sock_read (BIO *h, char *buf, int size)
 
static int my_sock_write (BIO *h, const char *buf, int size)
 
static BIO_METHOD * my_BIO_s_socket (void)
 
static int my_SSL_set_fd (PGconn *conn, int fd)
 
void pgtls_init_library (bool do_ssl, int do_crypto)
 
PostgresPollingStatusType pgtls_open_client (PGconn *conn)
 
ssize_t pgtls_read (PGconn *conn, void *ptr, size_t len)
 
bool pgtls_read_pending (PGconn *conn)
 
ssize_t pgtls_write (PGconn *conn, const void *ptr, size_t len)
 
char * pgtls_get_finished (PGconn *conn, size_t *len)
 
char * pgtls_get_peer_certificate_hash (PGconn *conn, size_t *len)
 
int pgtls_verify_peer_name_matches_certificate_guts (PGconn *conn, int *names_examined, char **first_name)
 
int pgtls_init (PGconn *conn)
 
void pgtls_close (PGconn *conn)
 
void * PQgetssl (PGconn *conn)
 
void * PQsslStruct (PGconn *conn, const char *struct_name)
 
const char *const * PQsslAttributeNames (PGconn *conn)
 
const char * PQsslAttribute (PGconn *conn, const char *attribute_name)
 

Variables

static bool pq_init_ssl_lib = true
 
static bool pq_init_crypto_lib = true
 
static bool ssl_lib_initialized = false
 
static char ssl_nomem [] = "out of memory allocating error description"
 
static BIO_METHOD * my_bio_methods
 

Macro Definition Documentation

◆ BIO_get_data

#define BIO_get_data (   bio)    (bio->ptr)

Definition at line 1480 of file fe-secure-openssl.c.

Referenced by my_sock_read(), and my_sock_write().

◆ BIO_set_data

#define BIO_set_data (   bio,
  data 
)    (bio->ptr = data)

Definition at line 1481 of file fe-secure-openssl.c.

Referenced by my_SSL_set_fd().

◆ SSL_ERR_LEN

#define SSL_ERR_LEN   128

Definition at line 1362 of file fe-secure-openssl.c.

Referenced by SSLerrmessage().

Function Documentation

◆ destroy_ssl_system()

static void destroy_ssl_system ( void  )
static

Definition at line 760 of file fe-secure-openssl.c.

References pq_init_crypto_lib, pthread_mutex_lock(), and pthread_mutex_unlock().

Referenced by pgtls_close().

761 {
762 #if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK)
763  /* Mutex is created in initialize_ssl_system() */
764  if (pthread_mutex_lock(&ssl_config_mutex))
765  return;
766 
767  if (pq_init_crypto_lib && ssl_open_connections > 0)
768  --ssl_open_connections;
769 
770  if (pq_init_crypto_lib && ssl_open_connections == 0)
771  {
772  /*
773  * No connections left, unregister libcrypto callbacks, if no one
774  * registered different ones in the meantime.
775  */
776  if (CRYPTO_get_locking_callback() == pq_lockingcallback)
777  CRYPTO_set_locking_callback(NULL);
778  if (CRYPTO_get_id_callback() == pq_threadidcallback)
779  CRYPTO_set_id_callback(NULL);
780 
781  /*
782  * We don't free the lock array. If we get another connection in this
783  * process, we will just re-use them with the existing mutexes.
784  *
785  * This means we leak a little memory on repeated load/unload of the
786  * library.
787  */
788  }
789 
790  pthread_mutex_unlock(&ssl_config_mutex);
791 #endif
792 }
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54
static bool pq_init_crypto_lib

◆ initialize_SSL()

static int initialize_SSL ( PGconn conn)
static

Definition at line 801 of file fe-secure-openssl.c.

References pg_conn::errorMessage, free, libpq_gettext, MAXPGPATH, my_SSL_set_fd(), pqGetHomeDirectory(), pqStrerror(), printfPQExpBuffer(), S_IRWXG, S_IRWXO, S_ISREG, snprintf(), pg_conn::sock, SSL_context, pg_conn::ssl_in_use, pg_conn::sslcert, pg_conn::sslcompression, pg_conn::sslcrl, SSLerrfree(), SSLerrmessage(), pg_conn::sslkey, pg_conn::sslmode, pg_conn::sslrootcert, stat, strlcpy(), and verify_cb().

Referenced by pgtls_open_client().

802 {
803  SSL_CTX *SSL_context;
804  struct stat buf;
805  char homedir[MAXPGPATH];
806  char fnbuf[MAXPGPATH];
807  char sebuf[256];
808  bool have_homedir;
809  bool have_cert;
810  bool have_rootcert;
811  EVP_PKEY *pkey = NULL;
812 
813  /*
814  * We'll need the home directory if any of the relevant parameters are
815  * defaulted. If pqGetHomeDirectory fails, act as though none of the
816  * files could be found.
817  */
818  if (!(conn->sslcert && strlen(conn->sslcert) > 0) ||
819  !(conn->sslkey && strlen(conn->sslkey) > 0) ||
820  !(conn->sslrootcert && strlen(conn->sslrootcert) > 0) ||
821  !(conn->sslcrl && strlen(conn->sslcrl) > 0))
822  have_homedir = pqGetHomeDirectory(homedir, sizeof(homedir));
823  else /* won't need it */
824  have_homedir = false;
825 
826  /*
827  * Create a new SSL_CTX object.
828  *
829  * We used to share a single SSL_CTX between all connections, but it was
830  * complicated if connections used different certificates. So now we
831  * create a separate context for each connection, and accept the overhead.
832  */
833  SSL_context = SSL_CTX_new(SSLv23_method());
834  if (!SSL_context)
835  {
836  char *err = SSLerrmessage(ERR_get_error());
837 
839  libpq_gettext("could not create SSL context: %s\n"),
840  err);
841  SSLerrfree(err);
842  return -1;
843  }
844 
845  /* Disable old protocol versions */
846  SSL_CTX_set_options(SSL_context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
847 
848  /*
849  * Disable OpenSSL's moving-write-buffer sanity check, because it causes
850  * unnecessary failures in nonblocking send cases.
851  */
852  SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
853 
854  /*
855  * If the root cert file exists, load it so we can perform certificate
856  * verification. If sslmode is "verify-full" we will also do further
857  * verification after the connection has been completed.
858  */
859  if (conn->sslrootcert && strlen(conn->sslrootcert) > 0)
860  strlcpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
861  else if (have_homedir)
862  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
863  else
864  fnbuf[0] = '\0';
865 
866  if (fnbuf[0] != '\0' &&
867  stat(fnbuf, &buf) == 0)
868  {
869  X509_STORE *cvstore;
870 
871  if (SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL) != 1)
872  {
873  char *err = SSLerrmessage(ERR_get_error());
874 
876  libpq_gettext("could not read root certificate file \"%s\": %s\n"),
877  fnbuf, err);
878  SSLerrfree(err);
879  SSL_CTX_free(SSL_context);
880  return -1;
881  }
882 
883  if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
884  {
885  if (conn->sslcrl && strlen(conn->sslcrl) > 0)
886  strlcpy(fnbuf, conn->sslcrl, sizeof(fnbuf));
887  else if (have_homedir)
888  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE);
889  else
890  fnbuf[0] = '\0';
891 
892  /* Set the flags to check against the complete CRL chain */
893  if (fnbuf[0] != '\0' &&
894  X509_STORE_load_locations(cvstore, fnbuf, NULL) == 1)
895  {
896  /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
897 #ifdef X509_V_FLAG_CRL_CHECK
898  X509_STORE_set_flags(cvstore,
899  X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
900 #else
901  char *err = SSLerrmessage(ERR_get_error());
902 
904  libpq_gettext("SSL library does not support CRL certificates (file \"%s\")\n"),
905  fnbuf);
906  SSLerrfree(err);
907  SSL_CTX_free(SSL_context);
908  return -1;
909 #endif
910  }
911  /* if not found, silently ignore; we do not require CRL */
912  ERR_clear_error();
913  }
914  have_rootcert = true;
915  }
916  else
917  {
918  /*
919  * stat() failed; assume root file doesn't exist. If sslmode is
920  * verify-ca or verify-full, this is an error. Otherwise, continue
921  * without performing any server cert verification.
922  */
923  if (conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */
924  {
925  /*
926  * The only way to reach here with an empty filename is if
927  * pqGetHomeDirectory failed. That's a sufficiently unusual case
928  * that it seems worth having a specialized error message for it.
929  */
930  if (fnbuf[0] == '\0')
932  libpq_gettext("could not get home directory to locate root certificate file\n"
933  "Either provide the file or change sslmode to disable server certificate verification.\n"));
934  else
936  libpq_gettext("root certificate file \"%s\" does not exist\n"
937  "Either provide the file or change sslmode to disable server certificate verification.\n"), fnbuf);
938  SSL_CTX_free(SSL_context);
939  return -1;
940  }
941  have_rootcert = false;
942  }
943 
944  /* Read the client certificate file */
945  if (conn->sslcert && strlen(conn->sslcert) > 0)
946  strlcpy(fnbuf, conn->sslcert, sizeof(fnbuf));
947  else if (have_homedir)
948  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
949  else
950  fnbuf[0] = '\0';
951 
952  if (fnbuf[0] == '\0')
953  {
954  /* no home directory, proceed without a client cert */
955  have_cert = false;
956  }
957  else if (stat(fnbuf, &buf) != 0)
958  {
959  /*
960  * If file is not present, just go on without a client cert; server
961  * might or might not accept the connection. Any other error,
962  * however, is grounds for complaint.
963  */
964  if (errno != ENOENT && errno != ENOTDIR)
965  {
967  libpq_gettext("could not open certificate file \"%s\": %s\n"),
968  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
969  SSL_CTX_free(SSL_context);
970  return -1;
971  }
972  have_cert = false;
973  }
974  else
975  {
976  /*
977  * Cert file exists, so load it. Since OpenSSL doesn't provide the
978  * equivalent of "SSL_use_certificate_chain_file", we have to load it
979  * into the SSL context, rather than the SSL object.
980  */
981  if (SSL_CTX_use_certificate_chain_file(SSL_context, fnbuf) != 1)
982  {
983  char *err = SSLerrmessage(ERR_get_error());
984 
986  libpq_gettext("could not read certificate file \"%s\": %s\n"),
987  fnbuf, err);
988  SSLerrfree(err);
989  SSL_CTX_free(SSL_context);
990  return -1;
991  }
992 
993  /* need to load the associated private key, too */
994  have_cert = true;
995  }
996 
997  /*
998  * The SSL context is now loaded with the correct root and client
999  * certificates. Create a connection-specific SSL object. The private key
1000  * is loaded directly into the SSL object. (We could load the private key
1001  * into the context, too, but we have done it this way historically, and
1002  * it doesn't really matter.)
1003  */
1004  if (!(conn->ssl = SSL_new(SSL_context)) ||
1005  !SSL_set_app_data(conn->ssl, conn) ||
1006  !my_SSL_set_fd(conn, conn->sock))
1007  {
1008  char *err = SSLerrmessage(ERR_get_error());
1009 
1011  libpq_gettext("could not establish SSL connection: %s\n"),
1012  err);
1013  SSLerrfree(err);
1014  SSL_CTX_free(SSL_context);
1015  return -1;
1016  }
1017  conn->ssl_in_use = true;
1018 
1019  /*
1020  * SSL contexts are reference counted by OpenSSL. We can free it as soon
1021  * as we have created the SSL object, and it will stick around for as long
1022  * as it's actually needed.
1023  */
1024  SSL_CTX_free(SSL_context);
1025  SSL_context = NULL;
1026 
1027  /*
1028  * Read the SSL key. If a key is specified, treat it as an engine:key
1029  * combination if there is colon present - we don't support files with
1030  * colon in the name. The exception is if the second character is a colon,
1031  * in which case it can be a Windows filename with drive specification.
1032  */
1033  if (have_cert && conn->sslkey && strlen(conn->sslkey) > 0)
1034  {
1035 #ifdef USE_SSL_ENGINE
1036  if (strchr(conn->sslkey, ':')
1037 #ifdef WIN32
1038  && conn->sslkey[1] != ':'
1039 #endif
1040  )
1041  {
1042  /* Colon, but not in second character, treat as engine:key */
1043  char *engine_str = strdup(conn->sslkey);
1044  char *engine_colon;
1045 
1046  if (engine_str == NULL)
1047  {
1049  libpq_gettext("out of memory\n"));
1050  return -1;
1051  }
1052 
1053  /* cannot return NULL because we already checked before strdup */
1054  engine_colon = strchr(engine_str, ':');
1055 
1056  *engine_colon = '\0'; /* engine_str now has engine name */
1057  engine_colon++; /* engine_colon now has key name */
1058 
1059  conn->engine = ENGINE_by_id(engine_str);
1060  if (conn->engine == NULL)
1061  {
1062  char *err = SSLerrmessage(ERR_get_error());
1063 
1065  libpq_gettext("could not load SSL engine \"%s\": %s\n"),
1066  engine_str, err);
1067  SSLerrfree(err);
1068  free(engine_str);
1069  return -1;
1070  }
1071 
1072  if (ENGINE_init(conn->engine) == 0)
1073  {
1074  char *err = SSLerrmessage(ERR_get_error());
1075 
1077  libpq_gettext("could not initialize SSL engine \"%s\": %s\n"),
1078  engine_str, err);
1079  SSLerrfree(err);
1080  ENGINE_free(conn->engine);
1081  conn->engine = NULL;
1082  free(engine_str);
1083  return -1;
1084  }
1085 
1086  pkey = ENGINE_load_private_key(conn->engine, engine_colon,
1087  NULL, NULL);
1088  if (pkey == NULL)
1089  {
1090  char *err = SSLerrmessage(ERR_get_error());
1091 
1093  libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"),
1094  engine_colon, engine_str, err);
1095  SSLerrfree(err);
1096  ENGINE_finish(conn->engine);
1097  ENGINE_free(conn->engine);
1098  conn->engine = NULL;
1099  free(engine_str);
1100  return -1;
1101  }
1102  if (SSL_use_PrivateKey(conn->ssl, pkey) != 1)
1103  {
1104  char *err = SSLerrmessage(ERR_get_error());
1105 
1107  libpq_gettext("could not load private SSL key \"%s\" from engine \"%s\": %s\n"),
1108  engine_colon, engine_str, err);
1109  SSLerrfree(err);
1110  ENGINE_finish(conn->engine);
1111  ENGINE_free(conn->engine);
1112  conn->engine = NULL;
1113  free(engine_str);
1114  return -1;
1115  }
1116 
1117  free(engine_str);
1118 
1119  fnbuf[0] = '\0'; /* indicate we're not going to load from a
1120  * file */
1121  }
1122  else
1123 #endif /* USE_SSL_ENGINE */
1124  {
1125  /* PGSSLKEY is not an engine, treat it as a filename */
1126  strlcpy(fnbuf, conn->sslkey, sizeof(fnbuf));
1127  }
1128  }
1129  else if (have_homedir)
1130  {
1131  /* No PGSSLKEY specified, load default file */
1132  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
1133  }
1134  else
1135  fnbuf[0] = '\0';
1136 
1137  if (have_cert && fnbuf[0] != '\0')
1138  {
1139  /* read the client key from file */
1140 
1141  if (stat(fnbuf, &buf) != 0)
1142  {
1144  libpq_gettext("certificate present, but not private key file \"%s\"\n"),
1145  fnbuf);
1146  return -1;
1147  }
1148 #ifndef WIN32
1149  if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
1150  {
1152  libpq_gettext("private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
1153  fnbuf);
1154  return -1;
1155  }
1156 #endif
1157 
1158  if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_PEM) != 1)
1159  {
1160  char *err = SSLerrmessage(ERR_get_error());
1161 
1163  libpq_gettext("could not load private key file \"%s\": %s\n"),
1164  fnbuf, err);
1165  SSLerrfree(err);
1166  return -1;
1167  }
1168  }
1169 
1170  /* verify that the cert and key go together */
1171  if (have_cert &&
1172  SSL_check_private_key(conn->ssl) != 1)
1173  {
1174  char *err = SSLerrmessage(ERR_get_error());
1175 
1177  libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
1178  fnbuf, err);
1179  SSLerrfree(err);
1180  return -1;
1181  }
1182 
1183  /*
1184  * If a root cert was loaded, also set our certificate verification
1185  * callback.
1186  */
1187  if (have_rootcert)
1188  SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, verify_cb);
1189 
1190  /*
1191  * Set compression option if the OpenSSL version used supports it (from
1192  * 1.0.0 on).
1193  */
1194 #ifdef SSL_OP_NO_COMPRESSION
1195  if (conn->sslcompression && conn->sslcompression[0] == '0')
1196  SSL_set_options(conn->ssl, SSL_OP_NO_COMPRESSION);
1197 
1198  /*
1199  * Mainline OpenSSL introduced SSL_clear_options() before
1200  * SSL_OP_NO_COMPRESSION, so this following #ifdef should not be
1201  * necessary, but some old NetBSD version have a locally modified libssl
1202  * that has SSL_OP_NO_COMPRESSION but not SSL_clear_options().
1203  */
1204 #ifdef HAVE_SSL_CLEAR_OPTIONS
1205  else
1206  SSL_clear_options(conn->ssl, SSL_OP_NO_COMPRESSION);
1207 #endif
1208 #endif
1209 
1210  return 0;
1211 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * pqStrerror(int errnum, char *strerrbuf, size_t buflen)
Definition: thread.c:61
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
char * sslkey
Definition: libpq-int.h:355
char * sslcompression
Definition: libpq-int.h:354
#define MAXPGPATH
bool ssl_in_use
Definition: libpq-int.h:458
static char * buf
Definition: pg_test_fsync.c:67
#define S_IRWXG
Definition: win32_port.h:292
static int verify_cb(int ok, X509_STORE_CTX *ctx)
pgsocket sock
Definition: libpq-int.h:401
#define S_ISREG(m)
Definition: win32_port.h:310
static int my_SSL_set_fd(PGconn *conn, int fd)
static void SSLerrfree(char *buf)
#define stat(a, b)
Definition: win32_port.h:266
char * sslmode
Definition: libpq-int.h:353
PQExpBufferData errorMessage
Definition: libpq-int.h:494
char * sslcert
Definition: libpq-int.h:356
#define free(a)
Definition: header.h:65
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * sslrootcert
Definition: libpq-int.h:357
static char * SSLerrmessage(unsigned long ecode)
static SSL_CTX * SSL_context
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:6543
char * sslcrl
Definition: libpq-int.h:358
#define S_IRWXO
Definition: win32_port.h:304
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ my_BIO_s_socket()

static BIO_METHOD * my_BIO_s_socket ( void  )
static

Definition at line 1547 of file fe-secure-openssl.c.

References malloc, my_bio_methods, my_sock_read(), and my_sock_write().

Referenced by my_SSL_set_fd().

1548 {
1549  if (!my_bio_methods)
1550  {
1551  BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
1552 #ifdef HAVE_BIO_METH_NEW
1553  int my_bio_index;
1554 
1555  my_bio_index = BIO_get_new_index();
1556  if (my_bio_index == -1)
1557  return NULL;
1558  my_bio_methods = BIO_meth_new(my_bio_index, "libpq socket");
1559  if (!my_bio_methods)
1560  return NULL;
1561 
1562  /*
1563  * As of this writing, these functions never fail. But check anyway,
1564  * like OpenSSL's own examples do.
1565  */
1566  if (!BIO_meth_set_write(my_bio_methods, my_sock_write) ||
1567  !BIO_meth_set_read(my_bio_methods, my_sock_read) ||
1568  !BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) ||
1569  !BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) ||
1570  !BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) ||
1571  !BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) ||
1572  !BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) ||
1573  !BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom)))
1574  {
1575  BIO_meth_free(my_bio_methods);
1576  my_bio_methods = NULL;
1577  return NULL;
1578  }
1579 #else
1580  my_bio_methods = malloc(sizeof(BIO_METHOD));
1581  if (!my_bio_methods)
1582  return NULL;
1583  memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
1584  my_bio_methods->bread = my_sock_read;
1585  my_bio_methods->bwrite = my_sock_write;
1586 #endif
1587  }
1588  return my_bio_methods;
1589 }
static int my_sock_write(BIO *h, const char *buf, int size)
#define malloc(a)
Definition: header.h:50
static BIO_METHOD * my_bio_methods
static int my_sock_read(BIO *h, char *buf, int size)

◆ my_sock_read()

static int my_sock_read ( BIO *  h,
char *  buf,
int  size 
)
static

Definition at line 1487 of file fe-secure-openssl.c.

References BIO_get_data, EAGAIN, EINTR, EWOULDBLOCK, pqsecure_raw_read(), and SOCK_ERRNO.

Referenced by my_BIO_s_socket().

1488 {
1489  int res;
1490 
1491  res = pqsecure_raw_read((PGconn *) BIO_get_data(h), buf, size);
1492  BIO_clear_retry_flags(h);
1493  if (res < 0)
1494  {
1495  /* If we were interrupted, tell caller to retry */
1496  switch (SOCK_ERRNO)
1497  {
1498 #ifdef EAGAIN
1499  case EAGAIN:
1500 #endif
1501 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
1502  case EWOULDBLOCK:
1503 #endif
1504  case EINTR:
1505  BIO_set_retry_read(h);
1506  break;
1507 
1508  default:
1509  break;
1510  }
1511  }
1512 
1513  return res;
1514 }
#define EAGAIN
Definition: win32_port.h:332
ssize_t pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
Definition: fe-secure.c:232
#define SOCK_ERRNO
Definition: libpq-int.h:773
static char * buf
Definition: pg_test_fsync.c:67
#define EWOULDBLOCK
Definition: win32_port.h:340
#define EINTR
Definition: win32_port.h:334
#define BIO_get_data(bio)

◆ my_sock_write()

static int my_sock_write ( BIO *  h,
const char *  buf,
int  size 
)
static

Definition at line 1517 of file fe-secure-openssl.c.

References BIO_get_data, EAGAIN, EINTR, EWOULDBLOCK, pqsecure_raw_write(), and SOCK_ERRNO.

Referenced by my_BIO_s_socket().

1518 {
1519  int res;
1520 
1521  res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
1522  BIO_clear_retry_flags(h);
1523  if (res <= 0)
1524  {
1525  /* If we were interrupted, tell caller to retry */
1526  switch (SOCK_ERRNO)
1527  {
1528 #ifdef EAGAIN
1529  case EAGAIN:
1530 #endif
1531 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
1532  case EWOULDBLOCK:
1533 #endif
1534  case EINTR:
1535  BIO_set_retry_write(h);
1536  break;
1537 
1538  default:
1539  break;
1540  }
1541  }
1542 
1543  return res;
1544 }
#define EAGAIN
Definition: win32_port.h:332
#define SOCK_ERRNO
Definition: libpq-int.h:773
static char * buf
Definition: pg_test_fsync.c:67
ssize_t pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
Definition: fe-secure.c:309
#define EWOULDBLOCK
Definition: win32_port.h:340
#define EINTR
Definition: win32_port.h:334
#define BIO_get_data(bio)

◆ my_SSL_set_fd()

static int my_SSL_set_fd ( PGconn conn,
int  fd 
)
static

Definition at line 1593 of file fe-secure-openssl.c.

References BIO_set_data, and my_BIO_s_socket().

Referenced by initialize_SSL().

1594 {
1595  int ret = 0;
1596  BIO *bio;
1597  BIO_METHOD *bio_method;
1598 
1599  bio_method = my_BIO_s_socket();
1600  if (bio_method == NULL)
1601  {
1602  SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
1603  goto err;
1604  }
1605  bio = BIO_new(bio_method);
1606  if (bio == NULL)
1607  {
1608  SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
1609  goto err;
1610  }
1611  BIO_set_data(bio, conn);
1612 
1613  SSL_set_bio(conn->ssl, bio, bio);
1614  BIO_set_fd(bio, fd, BIO_NOCLOSE);
1615  ret = 1;
1616 err:
1617  return ret;
1618 }
#define BIO_set_data(bio, data)
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static BIO_METHOD * my_BIO_s_socket(void)

◆ open_client_SSL()

static PostgresPollingStatusType open_client_SSL ( PGconn conn)
static

Definition at line 1217 of file fe-secure-openssl.c.

References pg_conn::errorMessage, libpq_gettext, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, pgtls_close(), pq_verify_peer_name_matches_certificate(), printfPQExpBuffer(), SOCK_ERRNO, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pgtls_open_client().

1218 {
1219  int r;
1220 
1221  ERR_clear_error();
1222  r = SSL_connect(conn->ssl);
1223  if (r <= 0)
1224  {
1225  int err = SSL_get_error(conn->ssl, r);
1226  unsigned long ecode;
1227 
1228  ecode = ERR_get_error();
1229  switch (err)
1230  {
1231  case SSL_ERROR_WANT_READ:
1232  return PGRES_POLLING_READING;
1233 
1234  case SSL_ERROR_WANT_WRITE:
1235  return PGRES_POLLING_WRITING;
1236 
1237  case SSL_ERROR_SYSCALL:
1238  {
1239  char sebuf[256];
1240 
1241  if (r == -1)
1243  libpq_gettext("SSL SYSCALL error: %s\n"),
1244  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1245  else
1247  libpq_gettext("SSL SYSCALL error: EOF detected\n"));
1248  pgtls_close(conn);
1249  return PGRES_POLLING_FAILED;
1250  }
1251  case SSL_ERROR_SSL:
1252  {
1253  char *err = SSLerrmessage(ecode);
1254 
1256  libpq_gettext("SSL error: %s\n"),
1257  err);
1258  SSLerrfree(err);
1259  pgtls_close(conn);
1260  return PGRES_POLLING_FAILED;
1261  }
1262 
1263  default:
1265  libpq_gettext("unrecognized SSL error code: %d\n"),
1266  err);
1267  pgtls_close(conn);
1268  return PGRES_POLLING_FAILED;
1269  }
1270  }
1271 
1272  /*
1273  * We already checked the server certificate in initialize_SSL() using
1274  * SSL_CTX_set_verify(), if root.crt exists.
1275  */
1276 
1277  /* get server certificate */
1278  conn->peer = SSL_get_peer_certificate(conn->ssl);
1279  if (conn->peer == NULL)
1280  {
1281  char *err;
1282 
1283  err = SSLerrmessage(ERR_get_error());
1284 
1286  libpq_gettext("certificate could not be obtained: %s\n"),
1287  err);
1288  SSLerrfree(err);
1289  pgtls_close(conn);
1290  return PGRES_POLLING_FAILED;
1291  }
1292 
1294  {
1295  pgtls_close(conn);
1296  return PGRES_POLLING_FAILED;
1297  }
1298 
1299  /* SSL handshake is complete */
1300  return PGRES_POLLING_OK;
1301 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define SOCK_STRERROR
Definition: libpq-int.h:774
#define SOCK_ERRNO
Definition: libpq-int.h:773
bool pq_verify_peer_name_matches_certificate(PGconn *conn)
static void SSLerrfree(char *buf)
void pgtls_close(PGconn *conn)
PQExpBufferData errorMessage
Definition: libpq-int.h:494
static char * SSLerrmessage(unsigned long ecode)
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ openssl_verify_peer_name_matches_certificate_name()

static int openssl_verify_peer_name_matches_certificate_name ( PGconn conn,
ASN1_STRING *  name,
char **  store_name 
)
static

Definition at line 500 of file fe-secure-openssl.c.

References pg_conn::errorMessage, libpq_gettext, pq_verify_peer_name_matches_certificate_name(), and printfPQExpBuffer().

Referenced by pgtls_verify_peer_name_matches_certificate_guts().

502 {
503  int len;
504  const unsigned char *namedata;
505 
506  /* Should not happen... */
507  if (name_entry == NULL)
508  {
510  libpq_gettext("SSL certificate's name entry is missing\n"));
511  return -1;
512  }
513 
514  /*
515  * GEN_DNS can be only IA5String, equivalent to US ASCII.
516  */
517 #ifdef HAVE_ASN1_STRING_GET0_DATA
518  namedata = ASN1_STRING_get0_data(name_entry);
519 #else
520  namedata = ASN1_STRING_data(name_entry);
521 #endif
522  len = ASN1_STRING_length(name_entry);
523 
524  /* OK to cast from unsigned to plain char, since it's all ASCII. */
525  return pq_verify_peer_name_matches_certificate_name(conn, (const char *) namedata, len, store_name);
526 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int pq_verify_peer_name_matches_certificate_name(PGconn *conn, const char *namedata, size_t namelen, char **store_name)
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pgtls_close()

void pgtls_close ( PGconn conn)

Definition at line 1304 of file fe-secure-openssl.c.

References destroy_ssl_system(), and pg_conn::ssl_in_use.

Referenced by open_client_SSL(), pgtls_open_client(), and pqsecure_close().

1305 {
1306  bool destroy_needed = false;
1307 
1308  if (conn->ssl)
1309  {
1310  /*
1311  * We can't destroy everything SSL-related here due to the possible
1312  * later calls to OpenSSL routines which may need our thread
1313  * callbacks, so set a flag here and check at the end.
1314  */
1315  destroy_needed = true;
1316 
1317  SSL_shutdown(conn->ssl);
1318  SSL_free(conn->ssl);
1319  conn->ssl = NULL;
1320  conn->ssl_in_use = false;
1321  }
1322 
1323  if (conn->peer)
1324  {
1325  X509_free(conn->peer);
1326  conn->peer = NULL;
1327  }
1328 
1329 #ifdef USE_SSL_ENGINE
1330  if (conn->engine)
1331  {
1332  ENGINE_finish(conn->engine);
1333  ENGINE_free(conn->engine);
1334  conn->engine = NULL;
1335  }
1336 #endif
1337 
1338  /*
1339  * This will remove our SSL locking hooks, if this is the last SSL
1340  * connection, which means we must wait to call it until after all SSL
1341  * calls have been made, otherwise we can end up with a race condition and
1342  * possible deadlocks.
1343  *
1344  * See comments above destroy_ssl_system().
1345  */
1346  if (destroy_needed)
1348 }
bool ssl_in_use
Definition: libpq-int.h:458
static void destroy_ssl_system(void)

◆ pgtls_get_finished()

char* pgtls_get_finished ( PGconn conn,
size_t *  len 
)

Definition at line 373 of file fe-secure-openssl.c.

References malloc.

Referenced by build_client_final_message().

374 {
375  char dummy[1];
376  char *result;
377 
378  /*
379  * OpenSSL does not offer an API to get directly the length of the TLS
380  * Finished message sent, so first do a dummy call to grab this
381  * information and then do an allocation with the correct size.
382  */
383  *len = SSL_get_finished(conn->ssl, dummy, sizeof(dummy));
384  result = malloc(*len);
385  if (result == NULL)
386  return NULL;
387  (void) SSL_get_finished(conn->ssl, result, *len);
388 
389  return result;
390 }
#define malloc(a)
Definition: header.h:50

◆ pgtls_get_peer_certificate_hash()

char* pgtls_get_peer_certificate_hash ( PGconn conn,
size_t *  len 
)

Definition at line 393 of file fe-secure-openssl.c.

References pg_conn::errorMessage, hash(), libpq_gettext, malloc, and printfPQExpBuffer().

Referenced by build_client_final_message().

394 {
395 #ifdef HAVE_X509_GET_SIGNATURE_NID
396  X509 *peer_cert;
397  const EVP_MD *algo_type;
398  unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
399  unsigned int hash_size;
400  int algo_nid;
401  char *cert_hash;
402 
403  *len = 0;
404 
405  if (!conn->peer)
406  return NULL;
407 
408  peer_cert = conn->peer;
409 
410  /*
411  * Get the signature algorithm of the certificate to determine the hash
412  * algorithm to use for the result.
413  */
414  if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert),
415  &algo_nid, NULL))
416  {
418  libpq_gettext("could not determine server certificate signature algorithm\n"));
419  return NULL;
420  }
421 
422  /*
423  * The TLS server's certificate bytes need to be hashed with SHA-256 if
424  * its signature algorithm is MD5 or SHA-1 as per RFC 5929
425  * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
426  * is used, the same hash as the signature algorithm is used.
427  */
428  switch (algo_nid)
429  {
430  case NID_md5:
431  case NID_sha1:
432  algo_type = EVP_sha256();
433  break;
434  default:
435  algo_type = EVP_get_digestbynid(algo_nid);
436  if (algo_type == NULL)
437  {
439  libpq_gettext("could not find digest for NID %s\n"),
440  OBJ_nid2sn(algo_nid));
441  return NULL;
442  }
443  break;
444  }
445 
446  if (!X509_digest(peer_cert, algo_type, hash, &hash_size))
447  {
449  libpq_gettext("could not generate peer certificate hash\n"));
450  return NULL;
451  }
452 
453  /* save result */
454  cert_hash = malloc(hash_size);
455  if (cert_hash == NULL)
456  {
458  libpq_gettext("out of memory\n"));
459  return NULL;
460  }
461  memcpy(cert_hash, hash, hash_size);
462  *len = hash_size;
463 
464  return cert_hash;
465 #else
467  libpq_gettext("channel binding type \"tls-server-end-point\" is not supported by this build\n"));
468  return NULL;
469 #endif
470 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define malloc(a)
Definition: header.h:50
PQExpBufferData errorMessage
Definition: libpq-int.h:494
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:541
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pgtls_init()

int pgtls_init ( PGconn conn)

Definition at line 662 of file fe-secure-openssl.c.

References free, i, malloc, pq_init_crypto_lib, pq_init_ssl_lib, pthread_mutex_init(), pthread_mutex_lock(), pthread_mutex_unlock(), and ssl_lib_initialized.

Referenced by pqsecure_initialize().

663 {
664 #ifdef ENABLE_THREAD_SAFETY
665 #ifdef WIN32
666  /* Also see similar code in fe-connect.c, default_threadlock() */
667  if (ssl_config_mutex == NULL)
668  {
669  while (InterlockedExchange(&win32_ssl_create_mutex, 1) == 1)
670  /* loop, another thread own the lock */ ;
671  if (ssl_config_mutex == NULL)
672  {
673  if (pthread_mutex_init(&ssl_config_mutex, NULL))
674  return -1;
675  }
676  InterlockedExchange(&win32_ssl_create_mutex, 0);
677  }
678 #endif
679  if (pthread_mutex_lock(&ssl_config_mutex))
680  return -1;
681 
682 #ifdef HAVE_CRYPTO_LOCK
683  if (pq_init_crypto_lib)
684  {
685  /*
686  * If necessary, set up an array to hold locks for libcrypto.
687  * libcrypto will tell us how big to make this array.
688  */
689  if (pq_lockarray == NULL)
690  {
691  int i;
692 
693  pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
694  if (!pq_lockarray)
695  {
696  pthread_mutex_unlock(&ssl_config_mutex);
697  return -1;
698  }
699  for (i = 0; i < CRYPTO_num_locks(); i++)
700  {
701  if (pthread_mutex_init(&pq_lockarray[i], NULL))
702  {
703  free(pq_lockarray);
704  pq_lockarray = NULL;
705  pthread_mutex_unlock(&ssl_config_mutex);
706  return -1;
707  }
708  }
709  }
710 
711  if (ssl_open_connections++ == 0)
712  {
713  /*
714  * These are only required for threaded libcrypto applications,
715  * but make sure we don't stomp on them if they're already set.
716  */
717  if (CRYPTO_get_id_callback() == NULL)
718  CRYPTO_set_id_callback(pq_threadidcallback);
719  if (CRYPTO_get_locking_callback() == NULL)
720  CRYPTO_set_locking_callback(pq_lockingcallback);
721  }
722  }
723 #endif /* HAVE_CRYPTO_LOCK */
724 #endif /* ENABLE_THREAD_SAFETY */
725 
726  if (!ssl_lib_initialized)
727  {
728  if (pq_init_ssl_lib)
729  {
730 #ifdef HAVE_OPENSSL_INIT_SSL
731  OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
732 #else
733  OPENSSL_config(NULL);
734  SSL_library_init();
735  SSL_load_error_strings();
736 #endif
737  }
738  ssl_lib_initialized = true;
739  }
740 
741 #ifdef ENABLE_THREAD_SAFETY
742  pthread_mutex_unlock(&ssl_config_mutex);
743 #endif
744  return 0;
745 }
static bool pq_init_ssl_lib
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8
int pthread_mutex_init(pthread_mutex_t *mp, void *attr)
Definition: pthread-win32.c:35
#define malloc(a)
Definition: header.h:50
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54
static bool pq_init_crypto_lib
#define free(a)
Definition: header.h:65
int i
static bool ssl_lib_initialized

◆ pgtls_init_library()

void pgtls_init_library ( bool  do_ssl,
int  do_crypto 
)

Definition at line 102 of file fe-secure-openssl.c.

References pq_init_crypto_lib, and pq_init_ssl_lib.

Referenced by PQinitOpenSSL(), and PQinitSSL().

103 {
104 #ifdef ENABLE_THREAD_SAFETY
105 
106  /*
107  * Disallow changing the flags while we have open connections, else we'd
108  * get completely confused.
109  */
110  if (ssl_open_connections != 0)
111  return;
112 #endif
113 
114  pq_init_ssl_lib = do_ssl;
115  pq_init_crypto_lib = do_crypto;
116 }
static bool pq_init_ssl_lib
static bool pq_init_crypto_lib

◆ pgtls_open_client()

PostgresPollingStatusType pgtls_open_client ( PGconn conn)

Definition at line 119 of file fe-secure-openssl.c.

References initialize_SSL(), open_client_SSL(), PGRES_POLLING_FAILED, and pgtls_close().

Referenced by pqsecure_open_client().

120 {
121  /* First time through? */
122  if (conn->ssl == NULL)
123  {
124  /*
125  * Create a connection-specific SSL object, and load client
126  * certificate, private key, and trusted CA certs.
127  */
128  if (initialize_SSL(conn) != 0)
129  {
130  /* initialize_SSL already put a message in conn->errorMessage */
131  pgtls_close(conn);
132  return PGRES_POLLING_FAILED;
133  }
134  }
135 
136  /* Begin or continue the actual handshake */
137  return open_client_SSL(conn);
138 }
static PostgresPollingStatusType open_client_SSL(PGconn *)
static int initialize_SSL(PGconn *conn)
void pgtls_close(PGconn *conn)

◆ pgtls_read()

ssize_t pgtls_read ( PGconn conn,
void *  ptr,
size_t  len 
)

Definition at line 141 of file fe-secure-openssl.c.

References ECONNRESET, pg_conn::errorMessage, libpq_gettext, printfPQExpBuffer(), SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_read().

142 {
143  ssize_t n;
144  int result_errno = 0;
145  char sebuf[256];
146  int err;
147  unsigned long ecode;
148 
149 rloop:
150 
151  /*
152  * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
153  * queue. In general, the current thread's error queue must be empty
154  * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
155  * not work reliably. Since the possibility exists that other OpenSSL
156  * clients running in the same thread but not under our control will fail
157  * to call ERR_get_error() themselves (after their own I/O operations),
158  * pro-actively clear the per-thread error queue now.
159  */
160  SOCK_ERRNO_SET(0);
161  ERR_clear_error();
162  n = SSL_read(conn->ssl, ptr, len);
163  err = SSL_get_error(conn->ssl, n);
164 
165  /*
166  * Other clients of OpenSSL may fail to call ERR_get_error(), but we
167  * always do, so as to not cause problems for OpenSSL clients that don't
168  * call ERR_clear_error() defensively. Be sure that this happens by
169  * calling now. SSL_get_error() relies on the OpenSSL per-thread error
170  * queue being intact, so this is the earliest possible point
171  * ERR_get_error() may be called.
172  */
173  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
174  switch (err)
175  {
176  case SSL_ERROR_NONE:
177  if (n < 0)
178  {
179  /* Not supposed to happen, so we don't translate the msg */
181  "SSL_read failed but did not provide error information\n");
182  /* assume the connection is broken */
183  result_errno = ECONNRESET;
184  }
185  break;
186  case SSL_ERROR_WANT_READ:
187  n = 0;
188  break;
189  case SSL_ERROR_WANT_WRITE:
190 
191  /*
192  * Returning 0 here would cause caller to wait for read-ready,
193  * which is not correct since what SSL wants is wait for
194  * write-ready. The former could get us stuck in an infinite
195  * wait, so don't risk it; busy-loop instead.
196  */
197  goto rloop;
198  case SSL_ERROR_SYSCALL:
199  if (n < 0)
200  {
201  result_errno = SOCK_ERRNO;
202  if (result_errno == EPIPE ||
203  result_errno == ECONNRESET)
206  "server closed the connection unexpectedly\n"
207  "\tThis probably means the server terminated abnormally\n"
208  "\tbefore or while processing the request.\n"));
209  else
211  libpq_gettext("SSL SYSCALL error: %s\n"),
212  SOCK_STRERROR(result_errno,
213  sebuf, sizeof(sebuf)));
214  }
215  else
216  {
218  libpq_gettext("SSL SYSCALL error: EOF detected\n"));
219  /* assume the connection is broken */
220  result_errno = ECONNRESET;
221  n = -1;
222  }
223  break;
224  case SSL_ERROR_SSL:
225  {
226  char *errm = SSLerrmessage(ecode);
227 
229  libpq_gettext("SSL error: %s\n"), errm);
230  SSLerrfree(errm);
231  /* assume the connection is broken */
232  result_errno = ECONNRESET;
233  n = -1;
234  break;
235  }
236  case SSL_ERROR_ZERO_RETURN:
237 
238  /*
239  * Per OpenSSL documentation, this error code is only returned for
240  * a clean connection closure, so we should not report it as a
241  * server crash.
242  */
244  libpq_gettext("SSL connection has been closed unexpectedly\n"));
245  result_errno = ECONNRESET;
246  n = -1;
247  break;
248  default:
250  libpq_gettext("unrecognized SSL error code: %d\n"),
251  err);
252  /* assume the connection is broken */
253  result_errno = ECONNRESET;
254  n = -1;
255  break;
256  }
257 
258  /* ensure we return the intended errno to caller */
259  SOCK_ERRNO_SET(result_errno);
260 
261  return n;
262 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define SOCK_STRERROR
Definition: libpq-int.h:774
#define SOCK_ERRNO
Definition: libpq-int.h:773
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:775
static void SSLerrfree(char *buf)
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define ECONNRESET
Definition: win32_port.h:344
static char * SSLerrmessage(unsigned long ecode)
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pgtls_read_pending()

bool pgtls_read_pending ( PGconn conn)

Definition at line 265 of file fe-secure-openssl.c.

Referenced by pqSocketCheck().

266 {
267  return SSL_pending(conn->ssl);
268 }

◆ pgtls_verify_peer_name_matches_certificate_guts()

int pgtls_verify_peer_name_matches_certificate_guts ( PGconn conn,
int *  names_examined,
char **  first_name 
)

Definition at line 534 of file fe-secure-openssl.c.

References free, i, name, openssl_verify_peer_name_matches_certificate_name(), pthread_mutex_lock(), pthread_mutex_unlock(), and pthread_self().

Referenced by pq_verify_peer_name_matches_certificate().

537 {
538  STACK_OF(GENERAL_NAME) *peer_san;
539  int i;
540  int rc = 0;
541 
542  /*
543  * First, get the Subject Alternative Names (SANs) from the certificate,
544  * and compare them against the originally given hostname.
545  */
546  peer_san = (STACK_OF(GENERAL_NAME) *)
547  X509_get_ext_d2i(conn->peer, NID_subject_alt_name, NULL, NULL);
548 
549  if (peer_san)
550  {
551  int san_len = sk_GENERAL_NAME_num(peer_san);
552 
553  for (i = 0; i < san_len; i++)
554  {
555  const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i);
556 
557  if (name->type == GEN_DNS)
558  {
559  char *alt_name;
560 
561  (*names_examined)++;
563  name->d.dNSName,
564  &alt_name);
565 
566  if (alt_name)
567  {
568  if (!*first_name)
569  *first_name = alt_name;
570  else
571  free(alt_name);
572  }
573  }
574  if (rc != 0)
575  break;
576  }
577  sk_GENERAL_NAME_free(peer_san);
578  }
579 
580  /*
581  * If there is no subjectAltName extension of type dNSName, check the
582  * Common Name.
583  *
584  * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
585  * dNSName is present, the CN must be ignored.)
586  */
587  if (*names_examined == 0)
588  {
589  X509_NAME *subject_name;
590 
591  subject_name = X509_get_subject_name(conn->peer);
592  if (subject_name != NULL)
593  {
594  int cn_index;
595 
596  cn_index = X509_NAME_get_index_by_NID(subject_name,
597  NID_commonName, -1);
598  if (cn_index >= 0)
599  {
600  (*names_examined)++;
602  conn,
603  X509_NAME_ENTRY_get_data(
604  X509_NAME_get_entry(subject_name, cn_index)),
605  first_name);
606  }
607  }
608  }
609 
610  return rc;
611 }
static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *name, char **store_name)
#define free(a)
Definition: header.h:65
const char * name
Definition: encode.c:521
int i

◆ pgtls_write()

ssize_t pgtls_write ( PGconn conn,
const void *  ptr,
size_t  len 
)

Definition at line 271 of file fe-secure-openssl.c.

References ECONNRESET, pg_conn::errorMessage, libpq_gettext, printfPQExpBuffer(), SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_write().

272 {
273  ssize_t n;
274  int result_errno = 0;
275  char sebuf[256];
276  int err;
277  unsigned long ecode;
278 
279  SOCK_ERRNO_SET(0);
280  ERR_clear_error();
281  n = SSL_write(conn->ssl, ptr, len);
282  err = SSL_get_error(conn->ssl, n);
283  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
284  switch (err)
285  {
286  case SSL_ERROR_NONE:
287  if (n < 0)
288  {
289  /* Not supposed to happen, so we don't translate the msg */
291  "SSL_write failed but did not provide error information\n");
292  /* assume the connection is broken */
293  result_errno = ECONNRESET;
294  }
295  break;
296  case SSL_ERROR_WANT_READ:
297 
298  /*
299  * Returning 0 here causes caller to wait for write-ready, which
300  * is not really the right thing, but it's the best we can do.
301  */
302  n = 0;
303  break;
304  case SSL_ERROR_WANT_WRITE:
305  n = 0;
306  break;
307  case SSL_ERROR_SYSCALL:
308  if (n < 0)
309  {
310  result_errno = SOCK_ERRNO;
311  if (result_errno == EPIPE || result_errno == ECONNRESET)
314  "server closed the connection unexpectedly\n"
315  "\tThis probably means the server terminated abnormally\n"
316  "\tbefore or while processing the request.\n"));
317  else
319  libpq_gettext("SSL SYSCALL error: %s\n"),
320  SOCK_STRERROR(result_errno,
321  sebuf, sizeof(sebuf)));
322  }
323  else
324  {
326  libpq_gettext("SSL SYSCALL error: EOF detected\n"));
327  /* assume the connection is broken */
328  result_errno = ECONNRESET;
329  n = -1;
330  }
331  break;
332  case SSL_ERROR_SSL:
333  {
334  char *errm = SSLerrmessage(ecode);
335 
337  libpq_gettext("SSL error: %s\n"), errm);
338  SSLerrfree(errm);
339  /* assume the connection is broken */
340  result_errno = ECONNRESET;
341  n = -1;
342  break;
343  }
344  case SSL_ERROR_ZERO_RETURN:
345 
346  /*
347  * Per OpenSSL documentation, this error code is only returned for
348  * a clean connection closure, so we should not report it as a
349  * server crash.
350  */
352  libpq_gettext("SSL connection has been closed unexpectedly\n"));
353  result_errno = ECONNRESET;
354  n = -1;
355  break;
356  default:
358  libpq_gettext("unrecognized SSL error code: %d\n"),
359  err);
360  /* assume the connection is broken */
361  result_errno = ECONNRESET;
362  n = -1;
363  break;
364  }
365 
366  /* ensure we return the intended errno to caller */
367  SOCK_ERRNO_SET(result_errno);
368 
369  return n;
370 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define SOCK_STRERROR
Definition: libpq-int.h:774
#define SOCK_ERRNO
Definition: libpq-int.h:773
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:775
static void SSLerrfree(char *buf)
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define ECONNRESET
Definition: win32_port.h:344
static char * SSLerrmessage(unsigned long ecode)
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ PQgetssl()

void* PQgetssl ( PGconn conn)

Definition at line 1403 of file fe-secure-openssl.c.

1404 {
1405  if (!conn)
1406  return NULL;
1407  return conn->ssl;
1408 }

◆ PQsslAttribute()

const char* PQsslAttribute ( PGconn conn,
const char *  attribute_name 
)

Definition at line 1436 of file fe-secure-openssl.c.

Referenced by printSSLInfo().

1437 {
1438  if (!conn)
1439  return NULL;
1440  if (conn->ssl == NULL)
1441  return NULL;
1442 
1443  if (strcmp(attribute_name, "library") == 0)
1444  return "OpenSSL";
1445 
1446  if (strcmp(attribute_name, "key_bits") == 0)
1447  {
1448  static char sslbits_str[12];
1449  int sslbits;
1450 
1451  SSL_get_cipher_bits(conn->ssl, &sslbits);
1452  snprintf(sslbits_str, sizeof(sslbits_str), "%d", sslbits);
1453  return sslbits_str;
1454  }
1455 
1456  if (strcmp(attribute_name, "cipher") == 0)
1457  return SSL_get_cipher(conn->ssl);
1458 
1459  if (strcmp(attribute_name, "compression") == 0)
1460  return SSL_get_current_compression(conn->ssl) ? "on" : "off";
1461 
1462  if (strcmp(attribute_name, "protocol") == 0)
1463  return SSL_get_version(conn->ssl);
1464 
1465  return NULL; /* unknown attribute */
1466 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define SSL_get_current_compression(x)
Definition: port.h:400

◆ PQsslAttributeNames()

const char* const* PQsslAttributeNames ( PGconn conn)

Definition at line 1421 of file fe-secure-openssl.c.

1422 {
1423  static const char *const result[] = {
1424  "library",
1425  "key_bits",
1426  "cipher",
1427  "compression",
1428  "protocol",
1429  NULL
1430  };
1431 
1432  return result;
1433 }

◆ PQsslStruct()

void* PQsslStruct ( PGconn conn,
const char *  struct_name 
)

Definition at line 1411 of file fe-secure-openssl.c.

1412 {
1413  if (!conn)
1414  return NULL;
1415  if (strcmp(struct_name, "OpenSSL") == 0)
1416  return conn->ssl;
1417  return NULL;
1418 }

◆ SSLerrfree()

static void SSLerrfree ( char *  buf)
static

Definition at line 1389 of file fe-secure-openssl.c.

References free, and ssl_nomem.

Referenced by initialize_SSL(), open_client_SSL(), pgtls_read(), and pgtls_write().

1390 {
1391  if (buf != ssl_nomem)
1392  free(buf);
1393 }
static char ssl_nomem[]
static char * buf
Definition: pg_test_fsync.c:67
#define free(a)
Definition: header.h:65

◆ SSLerrmessage()

static char * SSLerrmessage ( unsigned long  ecode)
static

Definition at line 1365 of file fe-secure-openssl.c.

References libpq_gettext, malloc, snprintf(), SSL_ERR_LEN, ssl_nomem, and strlcpy().

Referenced by initialize_SSL(), open_client_SSL(), pgtls_read(), and pgtls_write().

1366 {
1367  const char *errreason;
1368  char *errbuf;
1369 
1370  errbuf = malloc(SSL_ERR_LEN);
1371  if (!errbuf)
1372  return ssl_nomem;
1373  if (ecode == 0)
1374  {
1375  snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("no SSL error reported"));
1376  return errbuf;
1377  }
1378  errreason = ERR_reason_error_string(ecode);
1379  if (errreason != NULL)
1380  {
1381  strlcpy(errbuf, errreason, SSL_ERR_LEN);
1382  return errbuf;
1383  }
1384  snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("SSL error code %lu"), ecode);
1385  return errbuf;
1386 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define malloc(a)
Definition: header.h:50
static char ssl_nomem[]
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define SSL_ERR_LEN
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ verify_cb()

static int verify_cb ( int  ok,
X509_STORE_CTX *  ctx 
)
static

Definition at line 488 of file fe-secure-openssl.c.

Referenced by initialize_SSL().

489 {
490  return ok;
491 }

Variable Documentation

◆ my_bio_methods

BIO_METHOD* my_bio_methods
static

Definition at line 1484 of file fe-secure-openssl.c.

Referenced by my_BIO_s_socket().

◆ pq_init_crypto_lib

bool pq_init_crypto_lib = true
static

Definition at line 81 of file fe-secure-openssl.c.

Referenced by destroy_ssl_system(), pgtls_init(), and pgtls_init_library().

◆ pq_init_ssl_lib

bool pq_init_ssl_lib = true
static

Definition at line 80 of file fe-secure-openssl.c.

Referenced by pgtls_init(), and pgtls_init_library().

◆ ssl_lib_initialized

bool ssl_lib_initialized = false
static

Definition at line 83 of file fe-secure-openssl.c.

Referenced by pgtls_init().

◆ ssl_nomem

char ssl_nomem[] = "out of memory allocating error description"
static

Definition at line 1360 of file fe-secure-openssl.c.

Referenced by SSLerrfree(), and SSLerrmessage().