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 "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 bool verify_peer_name_matches_certificate (PGconn *)
 
static int verify_cb (int ok, X509_STORE_CTX *ctx)
 
static int 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)
 
bool pgtls_read_pending (PGconn *conn)
 
ssize_t pgtls_read (PGconn *conn, void *ptr, size_t len)
 
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)
 
static int wildcard_certificate_match (const char *pattern, const char *string)
 
int pgtls_init (PGconn *conn)
 
void pgtls_close (PGconn *conn)
 
int PQsslInUse (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 1684 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 1685 of file fe-secure-openssl.c.

Referenced by my_SSL_set_fd().

◆ SSL_ERR_LEN

#define SSL_ERR_LEN   128

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

Referenced by SSLerrmessage().

Function Documentation

◆ destroy_ssl_system()

static void destroy_ssl_system ( void  )
static

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

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

Referenced by pgtls_close().

963 {
964 #if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK)
965  /* Mutex is created in initialize_ssl_system() */
966  if (pthread_mutex_lock(&ssl_config_mutex))
967  return;
968 
969  if (pq_init_crypto_lib && ssl_open_connections > 0)
970  --ssl_open_connections;
971 
972  if (pq_init_crypto_lib && ssl_open_connections == 0)
973  {
974  /*
975  * No connections left, unregister libcrypto callbacks, if no one
976  * registered different ones in the meantime.
977  */
978  if (CRYPTO_get_locking_callback() == pq_lockingcallback)
979  CRYPTO_set_locking_callback(NULL);
980  if (CRYPTO_get_id_callback() == pq_threadidcallback)
981  CRYPTO_set_id_callback(NULL);
982 
983  /*
984  * We don't free the lock array. If we get another connection in this
985  * process, we will just re-use them with the existing mutexes.
986  *
987  * This means we leak a little memory on repeated load/unload of the
988  * library.
989  */
990  }
991 
992  pthread_mutex_unlock(&ssl_config_mutex);
993 #endif
994 }
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 1003 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().

1004 {
1005  SSL_CTX *SSL_context;
1006  struct stat buf;
1007  char homedir[MAXPGPATH];
1008  char fnbuf[MAXPGPATH];
1009  char sebuf[256];
1010  bool have_homedir;
1011  bool have_cert;
1012  bool have_rootcert;
1013  EVP_PKEY *pkey = NULL;
1014 
1015  /*
1016  * We'll need the home directory if any of the relevant parameters are
1017  * defaulted. If pqGetHomeDirectory fails, act as though none of the
1018  * files could be found.
1019  */
1020  if (!(conn->sslcert && strlen(conn->sslcert) > 0) ||
1021  !(conn->sslkey && strlen(conn->sslkey) > 0) ||
1022  !(conn->sslrootcert && strlen(conn->sslrootcert) > 0) ||
1023  !(conn->sslcrl && strlen(conn->sslcrl) > 0))
1024  have_homedir = pqGetHomeDirectory(homedir, sizeof(homedir));
1025  else /* won't need it */
1026  have_homedir = false;
1027 
1028  /*
1029  * Create a new SSL_CTX object.
1030  *
1031  * We used to share a single SSL_CTX between all connections, but it was
1032  * complicated if connections used different certificates. So now we
1033  * create a separate context for each connection, and accept the overhead.
1034  */
1035  SSL_context = SSL_CTX_new(SSLv23_method());
1036  if (!SSL_context)
1037  {
1038  char *err = SSLerrmessage(ERR_get_error());
1039 
1041  libpq_gettext("could not create SSL context: %s\n"),
1042  err);
1043  SSLerrfree(err);
1044  return -1;
1045  }
1046 
1047  /* Disable old protocol versions */
1048  SSL_CTX_set_options(SSL_context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
1049 
1050  /*
1051  * Disable OpenSSL's moving-write-buffer sanity check, because it causes
1052  * unnecessary failures in nonblocking send cases.
1053  */
1054  SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
1055 
1056  /*
1057  * If the root cert file exists, load it so we can perform certificate
1058  * verification. If sslmode is "verify-full" we will also do further
1059  * verification after the connection has been completed.
1060  */
1061  if (conn->sslrootcert && strlen(conn->sslrootcert) > 0)
1062  strlcpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
1063  else if (have_homedir)
1064  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
1065  else
1066  fnbuf[0] = '\0';
1067 
1068  if (fnbuf[0] != '\0' &&
1069  stat(fnbuf, &buf) == 0)
1070  {
1071  X509_STORE *cvstore;
1072 
1073  if (SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL) != 1)
1074  {
1075  char *err = SSLerrmessage(ERR_get_error());
1076 
1078  libpq_gettext("could not read root certificate file \"%s\": %s\n"),
1079  fnbuf, err);
1080  SSLerrfree(err);
1081  SSL_CTX_free(SSL_context);
1082  return -1;
1083  }
1084 
1085  if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
1086  {
1087  if (conn->sslcrl && strlen(conn->sslcrl) > 0)
1088  strlcpy(fnbuf, conn->sslcrl, sizeof(fnbuf));
1089  else if (have_homedir)
1090  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE);
1091  else
1092  fnbuf[0] = '\0';
1093 
1094  /* Set the flags to check against the complete CRL chain */
1095  if (fnbuf[0] != '\0' &&
1096  X509_STORE_load_locations(cvstore, fnbuf, NULL) == 1)
1097  {
1098  /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
1099 #ifdef X509_V_FLAG_CRL_CHECK
1100  X509_STORE_set_flags(cvstore,
1101  X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
1102 #else
1103  char *err = SSLerrmessage(ERR_get_error());
1104 
1106  libpq_gettext("SSL library does not support CRL certificates (file \"%s\")\n"),
1107  fnbuf);
1108  SSLerrfree(err);
1109  SSL_CTX_free(SSL_context);
1110  return -1;
1111 #endif
1112  }
1113  /* if not found, silently ignore; we do not require CRL */
1114  ERR_clear_error();
1115  }
1116  have_rootcert = true;
1117  }
1118  else
1119  {
1120  /*
1121  * stat() failed; assume root file doesn't exist. If sslmode is
1122  * verify-ca or verify-full, this is an error. Otherwise, continue
1123  * without performing any server cert verification.
1124  */
1125  if (conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */
1126  {
1127  /*
1128  * The only way to reach here with an empty filename is if
1129  * pqGetHomeDirectory failed. That's a sufficiently unusual case
1130  * that it seems worth having a specialized error message for it.
1131  */
1132  if (fnbuf[0] == '\0')
1134  libpq_gettext("could not get home directory to locate root certificate file\n"
1135  "Either provide the file or change sslmode to disable server certificate verification.\n"));
1136  else
1138  libpq_gettext("root certificate file \"%s\" does not exist\n"
1139  "Either provide the file or change sslmode to disable server certificate verification.\n"), fnbuf);
1140  SSL_CTX_free(SSL_context);
1141  return -1;
1142  }
1143  have_rootcert = false;
1144  }
1145 
1146  /* Read the client certificate file */
1147  if (conn->sslcert && strlen(conn->sslcert) > 0)
1148  strlcpy(fnbuf, conn->sslcert, sizeof(fnbuf));
1149  else if (have_homedir)
1150  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
1151  else
1152  fnbuf[0] = '\0';
1153 
1154  if (fnbuf[0] == '\0')
1155  {
1156  /* no home directory, proceed without a client cert */
1157  have_cert = false;
1158  }
1159  else if (stat(fnbuf, &buf) != 0)
1160  {
1161  /*
1162  * If file is not present, just go on without a client cert; server
1163  * might or might not accept the connection. Any other error,
1164  * however, is grounds for complaint.
1165  */
1166  if (errno != ENOENT && errno != ENOTDIR)
1167  {
1169  libpq_gettext("could not open certificate file \"%s\": %s\n"),
1170  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
1171  SSL_CTX_free(SSL_context);
1172  return -1;
1173  }
1174  have_cert = false;
1175  }
1176  else
1177  {
1178  /*
1179  * Cert file exists, so load it. Since OpenSSL doesn't provide the
1180  * equivalent of "SSL_use_certificate_chain_file", we have to load it
1181  * into the SSL context, rather than the SSL object.
1182  */
1183  if (SSL_CTX_use_certificate_chain_file(SSL_context, fnbuf) != 1)
1184  {
1185  char *err = SSLerrmessage(ERR_get_error());
1186 
1188  libpq_gettext("could not read certificate file \"%s\": %s\n"),
1189  fnbuf, err);
1190  SSLerrfree(err);
1191  SSL_CTX_free(SSL_context);
1192  return -1;
1193  }
1194 
1195  /* need to load the associated private key, too */
1196  have_cert = true;
1197  }
1198 
1199  /*
1200  * The SSL context is now loaded with the correct root and client
1201  * certificates. Create a connection-specific SSL object. The private key
1202  * is loaded directly into the SSL object. (We could load the private key
1203  * into the context, too, but we have done it this way historically, and
1204  * it doesn't really matter.)
1205  */
1206  if (!(conn->ssl = SSL_new(SSL_context)) ||
1207  !SSL_set_app_data(conn->ssl, conn) ||
1208  !my_SSL_set_fd(conn, conn->sock))
1209  {
1210  char *err = SSLerrmessage(ERR_get_error());
1211 
1213  libpq_gettext("could not establish SSL connection: %s\n"),
1214  err);
1215  SSLerrfree(err);
1216  SSL_CTX_free(SSL_context);
1217  return -1;
1218  }
1219  conn->ssl_in_use = true;
1220 
1221  /*
1222  * SSL contexts are reference counted by OpenSSL. We can free it as soon
1223  * as we have created the SSL object, and it will stick around for as long
1224  * as it's actually needed.
1225  */
1226  SSL_CTX_free(SSL_context);
1227  SSL_context = NULL;
1228 
1229  /*
1230  * Read the SSL key. If a key is specified, treat it as an engine:key
1231  * combination if there is colon present - we don't support files with
1232  * colon in the name. The exception is if the second character is a colon,
1233  * in which case it can be a Windows filename with drive specification.
1234  */
1235  if (have_cert && conn->sslkey && strlen(conn->sslkey) > 0)
1236  {
1237 #ifdef USE_SSL_ENGINE
1238  if (strchr(conn->sslkey, ':')
1239 #ifdef WIN32
1240  && conn->sslkey[1] != ':'
1241 #endif
1242  )
1243  {
1244  /* Colon, but not in second character, treat as engine:key */
1245  char *engine_str = strdup(conn->sslkey);
1246  char *engine_colon;
1247 
1248  if (engine_str == NULL)
1249  {
1251  libpq_gettext("out of memory\n"));
1252  return -1;
1253  }
1254 
1255  /* cannot return NULL because we already checked before strdup */
1256  engine_colon = strchr(engine_str, ':');
1257 
1258  *engine_colon = '\0'; /* engine_str now has engine name */
1259  engine_colon++; /* engine_colon now has key name */
1260 
1261  conn->engine = ENGINE_by_id(engine_str);
1262  if (conn->engine == NULL)
1263  {
1264  char *err = SSLerrmessage(ERR_get_error());
1265 
1267  libpq_gettext("could not load SSL engine \"%s\": %s\n"),
1268  engine_str, err);
1269  SSLerrfree(err);
1270  free(engine_str);
1271  return -1;
1272  }
1273 
1274  if (ENGINE_init(conn->engine) == 0)
1275  {
1276  char *err = SSLerrmessage(ERR_get_error());
1277 
1279  libpq_gettext("could not initialize SSL engine \"%s\": %s\n"),
1280  engine_str, err);
1281  SSLerrfree(err);
1282  ENGINE_free(conn->engine);
1283  conn->engine = NULL;
1284  free(engine_str);
1285  return -1;
1286  }
1287 
1288  pkey = ENGINE_load_private_key(conn->engine, engine_colon,
1289  NULL, NULL);
1290  if (pkey == NULL)
1291  {
1292  char *err = SSLerrmessage(ERR_get_error());
1293 
1295  libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"),
1296  engine_colon, engine_str, err);
1297  SSLerrfree(err);
1298  ENGINE_finish(conn->engine);
1299  ENGINE_free(conn->engine);
1300  conn->engine = NULL;
1301  free(engine_str);
1302  return -1;
1303  }
1304  if (SSL_use_PrivateKey(conn->ssl, pkey) != 1)
1305  {
1306  char *err = SSLerrmessage(ERR_get_error());
1307 
1309  libpq_gettext("could not load private SSL key \"%s\" from engine \"%s\": %s\n"),
1310  engine_colon, engine_str, err);
1311  SSLerrfree(err);
1312  ENGINE_finish(conn->engine);
1313  ENGINE_free(conn->engine);
1314  conn->engine = NULL;
1315  free(engine_str);
1316  return -1;
1317  }
1318 
1319  free(engine_str);
1320 
1321  fnbuf[0] = '\0'; /* indicate we're not going to load from a
1322  * file */
1323  }
1324  else
1325 #endif /* USE_SSL_ENGINE */
1326  {
1327  /* PGSSLKEY is not an engine, treat it as a filename */
1328  strlcpy(fnbuf, conn->sslkey, sizeof(fnbuf));
1329  }
1330  }
1331  else if (have_homedir)
1332  {
1333  /* No PGSSLKEY specified, load default file */
1334  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
1335  }
1336  else
1337  fnbuf[0] = '\0';
1338 
1339  if (have_cert && fnbuf[0] != '\0')
1340  {
1341  /* read the client key from file */
1342 
1343  if (stat(fnbuf, &buf) != 0)
1344  {
1346  libpq_gettext("certificate present, but not private key file \"%s\"\n"),
1347  fnbuf);
1348  return -1;
1349  }
1350 #ifndef WIN32
1351  if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
1352  {
1354  libpq_gettext("private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
1355  fnbuf);
1356  return -1;
1357  }
1358 #endif
1359 
1360  if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_PEM) != 1)
1361  {
1362  char *err = SSLerrmessage(ERR_get_error());
1363 
1365  libpq_gettext("could not load private key file \"%s\": %s\n"),
1366  fnbuf, err);
1367  SSLerrfree(err);
1368  return -1;
1369  }
1370  }
1371 
1372  /* verify that the cert and key go together */
1373  if (have_cert &&
1374  SSL_check_private_key(conn->ssl) != 1)
1375  {
1376  char *err = SSLerrmessage(ERR_get_error());
1377 
1379  libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
1380  fnbuf, err);
1381  SSLerrfree(err);
1382  return -1;
1383  }
1384 
1385  /*
1386  * If a root cert was loaded, also set our certificate verification
1387  * callback.
1388  */
1389  if (have_rootcert)
1390  SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, verify_cb);
1391 
1392  /*
1393  * If the OpenSSL version used supports it (from 1.0.0 on) and the user
1394  * requested it, disable SSL compression.
1395  */
1396 #ifdef SSL_OP_NO_COMPRESSION
1397  if (conn->sslcompression && conn->sslcompression[0] == '0')
1398  {
1399  SSL_set_options(conn->ssl, SSL_OP_NO_COMPRESSION);
1400  }
1401 #endif
1402 
1403  return 0;
1404 }
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:6542
char * sslcrl
Definition: libpq-int.h:358
#define S_IRWXO
Definition: win32_port.h:304
#define libpq_gettext(x)
Definition: libpq-int.h:687

◆ my_BIO_s_socket()

static BIO_METHOD * my_BIO_s_socket ( void  )
static

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

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

Referenced by my_SSL_set_fd().

1752 {
1753  if (!my_bio_methods)
1754  {
1755  BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
1756 #ifdef HAVE_BIO_METH_NEW
1757  int my_bio_index;
1758 
1759  my_bio_index = BIO_get_new_index();
1760  if (my_bio_index == -1)
1761  return NULL;
1762  my_bio_methods = BIO_meth_new(my_bio_index, "libpq socket");
1763  if (!my_bio_methods)
1764  return NULL;
1765 
1766  /*
1767  * As of this writing, these functions never fail. But check anyway,
1768  * like OpenSSL's own examples do.
1769  */
1770  if (!BIO_meth_set_write(my_bio_methods, my_sock_write) ||
1771  !BIO_meth_set_read(my_bio_methods, my_sock_read) ||
1772  !BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) ||
1773  !BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) ||
1774  !BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) ||
1775  !BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) ||
1776  !BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) ||
1777  !BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom)))
1778  {
1779  BIO_meth_free(my_bio_methods);
1780  my_bio_methods = NULL;
1781  return NULL;
1782  }
1783 #else
1784  my_bio_methods = malloc(sizeof(BIO_METHOD));
1785  if (!my_bio_methods)
1786  return NULL;
1787  memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
1788  my_bio_methods->bread = my_sock_read;
1789  my_bio_methods->bwrite = my_sock_write;
1790 #endif
1791  }
1792  return my_bio_methods;
1793 }
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 1691 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().

1692 {
1693  int res;
1694 
1695  res = pqsecure_raw_read((PGconn *) BIO_get_data(h), buf, size);
1696  BIO_clear_retry_flags(h);
1697  if (res < 0)
1698  {
1699  /* If we were interrupted, tell caller to retry */
1700  switch (SOCK_ERRNO)
1701  {
1702 #ifdef EAGAIN
1703  case EAGAIN:
1704 #endif
1705 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
1706  case EWOULDBLOCK:
1707 #endif
1708  case EINTR:
1709  BIO_set_retry_read(h);
1710  break;
1711 
1712  default:
1713  break;
1714  }
1715  }
1716 
1717  return res;
1718 }
#define EAGAIN
Definition: win32_port.h:332
ssize_t pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
Definition: fe-secure.c:224
#define SOCK_ERRNO
Definition: libpq-int.h:700
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 1721 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().

1722 {
1723  int res;
1724 
1725  res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
1726  BIO_clear_retry_flags(h);
1727  if (res <= 0)
1728  {
1729  /* If we were interrupted, tell caller to retry */
1730  switch (SOCK_ERRNO)
1731  {
1732 #ifdef EAGAIN
1733  case EAGAIN:
1734 #endif
1735 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
1736  case EWOULDBLOCK:
1737 #endif
1738  case EINTR:
1739  BIO_set_retry_write(h);
1740  break;
1741 
1742  default:
1743  break;
1744  }
1745  }
1746 
1747  return res;
1748 }
#define EAGAIN
Definition: win32_port.h:332
#define SOCK_ERRNO
Definition: libpq-int.h:700
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:301
#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 1797 of file fe-secure-openssl.c.

References BIO_set_data, and my_BIO_s_socket().

Referenced by initialize_SSL().

1798 {
1799  int ret = 0;
1800  BIO *bio;
1801  BIO_METHOD *bio_method;
1802 
1803  bio_method = my_BIO_s_socket();
1804  if (bio_method == NULL)
1805  {
1806  SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
1807  goto err;
1808  }
1809  bio = BIO_new(bio_method);
1810  if (bio == NULL)
1811  {
1812  SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
1813  goto err;
1814  }
1815  BIO_set_data(bio, conn);
1816 
1817  SSL_set_bio(conn->ssl, bio, bio);
1818  BIO_set_fd(bio, fd, BIO_NOCLOSE);
1819  ret = 1;
1820 err:
1821  return ret;
1822 }
#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 1410 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(), printfPQExpBuffer(), SOCK_ERRNO, SOCK_STRERROR, SSLerrfree(), SSLerrmessage(), and verify_peer_name_matches_certificate().

Referenced by pgtls_open_client().

1411 {
1412  int r;
1413 
1414  ERR_clear_error();
1415  r = SSL_connect(conn->ssl);
1416  if (r <= 0)
1417  {
1418  int err = SSL_get_error(conn->ssl, r);
1419  unsigned long ecode;
1420 
1421  ecode = ERR_get_error();
1422  switch (err)
1423  {
1424  case SSL_ERROR_WANT_READ:
1425  return PGRES_POLLING_READING;
1426 
1427  case SSL_ERROR_WANT_WRITE:
1428  return PGRES_POLLING_WRITING;
1429 
1430  case SSL_ERROR_SYSCALL:
1431  {
1432  char sebuf[256];
1433 
1434  if (r == -1)
1436  libpq_gettext("SSL SYSCALL error: %s\n"),
1437  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1438  else
1440  libpq_gettext("SSL SYSCALL error: EOF detected\n"));
1441  pgtls_close(conn);
1442  return PGRES_POLLING_FAILED;
1443  }
1444  case SSL_ERROR_SSL:
1445  {
1446  char *err = SSLerrmessage(ecode);
1447 
1449  libpq_gettext("SSL error: %s\n"),
1450  err);
1451  SSLerrfree(err);
1452  pgtls_close(conn);
1453  return PGRES_POLLING_FAILED;
1454  }
1455 
1456  default:
1458  libpq_gettext("unrecognized SSL error code: %d\n"),
1459  err);
1460  pgtls_close(conn);
1461  return PGRES_POLLING_FAILED;
1462  }
1463  }
1464 
1465  /*
1466  * We already checked the server certificate in initialize_SSL() using
1467  * SSL_CTX_set_verify(), if root.crt exists.
1468  */
1469 
1470  /* get server certificate */
1471  conn->peer = SSL_get_peer_certificate(conn->ssl);
1472  if (conn->peer == NULL)
1473  {
1474  char *err;
1475 
1476  err = SSLerrmessage(ERR_get_error());
1477 
1479  libpq_gettext("certificate could not be obtained: %s\n"),
1480  err);
1481  SSLerrfree(err);
1482  pgtls_close(conn);
1483  return PGRES_POLLING_FAILED;
1484  }
1485 
1487  {
1488  pgtls_close(conn);
1489  return PGRES_POLLING_FAILED;
1490  }
1491 
1492  /* SSL handshake is complete */
1493  return PGRES_POLLING_OK;
1494 }
static bool verify_peer_name_matches_certificate(PGconn *)
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define SOCK_STRERROR
Definition: libpq-int.h:701
#define SOCK_ERRNO
Definition: libpq-int.h:700
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:687

◆ pgtls_close()

void pgtls_close ( PGconn conn)

Definition at line 1500 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().

1501 {
1502  bool destroy_needed = false;
1503 
1504  if (conn->ssl)
1505  {
1506  /*
1507  * We can't destroy everything SSL-related here due to the possible
1508  * later calls to OpenSSL routines which may need our thread
1509  * callbacks, so set a flag here and check at the end.
1510  */
1511  destroy_needed = true;
1512 
1513  SSL_shutdown(conn->ssl);
1514  SSL_free(conn->ssl);
1515  conn->ssl = NULL;
1516  conn->ssl_in_use = false;
1517  }
1518 
1519  if (conn->peer)
1520  {
1521  X509_free(conn->peer);
1522  conn->peer = NULL;
1523  }
1524 
1525 #ifdef USE_SSL_ENGINE
1526  if (conn->engine)
1527  {
1528  ENGINE_finish(conn->engine);
1529  ENGINE_free(conn->engine);
1530  conn->engine = NULL;
1531  }
1532 #endif
1533 
1534  /*
1535  * This will remove our SSL locking hooks, if this is the last SSL
1536  * connection, which means we must wait to call it until after all SSL
1537  * calls have been made, otherwise we can end up with a race condition and
1538  * possible deadlocks.
1539  *
1540  * See comments above destroy_ssl_system().
1541  */
1542  if (destroy_needed)
1544 }
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 403 of file fe-secure-openssl.c.

References malloc.

Referenced by build_client_final_message().

404 {
405  char dummy[1];
406  char *result;
407 
408  /*
409  * OpenSSL does not offer an API to get directly the length of the TLS
410  * Finished message sent, so first do a dummy call to grab this
411  * information and then do an allocation with the correct size.
412  */
413  *len = SSL_get_finished(conn->ssl, dummy, sizeof(dummy));
414  result = malloc(*len);
415  if (result == NULL)
416  return NULL;
417  (void) SSL_get_finished(conn->ssl, result, *len);
418 
419  return result;
420 }
#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 430 of file fe-secure-openssl.c.

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

Referenced by build_client_final_message().

431 {
432 #ifdef HAVE_X509_GET_SIGNATURE_NID
433  X509 *peer_cert;
434  const EVP_MD *algo_type;
435  unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
436  unsigned int hash_size;
437  int algo_nid;
438  char *cert_hash;
439 
440  *len = 0;
441 
442  if (!conn->peer)
443  return NULL;
444 
445  peer_cert = conn->peer;
446 
447  /*
448  * Get the signature algorithm of the certificate to determine the hash
449  * algorithm to use for the result.
450  */
451  if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert),
452  &algo_nid, NULL))
453  {
455  libpq_gettext("could not determine server certificate signature algorithm\n"));
456  return NULL;
457  }
458 
459  /*
460  * The TLS server's certificate bytes need to be hashed with SHA-256 if
461  * its signature algorithm is MD5 or SHA-1 as per RFC 5929
462  * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
463  * is used, the same hash as the signature algorithm is used.
464  */
465  switch (algo_nid)
466  {
467  case NID_md5:
468  case NID_sha1:
469  algo_type = EVP_sha256();
470  break;
471  default:
472  algo_type = EVP_get_digestbynid(algo_nid);
473  if (algo_type == NULL)
474  {
476  libpq_gettext("could not find digest for NID %s\n"),
477  OBJ_nid2sn(algo_nid));
478  return NULL;
479  }
480  break;
481  }
482 
483  if (!X509_digest(peer_cert, algo_type, hash, &hash_size))
484  {
486  libpq_gettext("could not generate peer certificate hash\n"));
487  return NULL;
488  }
489 
490  /* save result */
491  cert_hash = malloc(hash_size);
492  if (cert_hash == NULL)
493  {
495  libpq_gettext("out of memory\n"));
496  return NULL;
497  }
498  memcpy(cert_hash, hash, hash_size);
499  *len = hash_size;
500 
501  return cert_hash;
502 #else
504  libpq_gettext("channel binding type \"tls-server-end-point\" is not supported by this build\n"));
505  return NULL;
506 #endif
507 }
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:687

◆ pgtls_init()

int pgtls_init ( PGconn conn)

Definition at line 864 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().

865 {
866 #ifdef ENABLE_THREAD_SAFETY
867 #ifdef WIN32
868  /* Also see similar code in fe-connect.c, default_threadlock() */
869  if (ssl_config_mutex == NULL)
870  {
871  while (InterlockedExchange(&win32_ssl_create_mutex, 1) == 1)
872  /* loop, another thread own the lock */ ;
873  if (ssl_config_mutex == NULL)
874  {
875  if (pthread_mutex_init(&ssl_config_mutex, NULL))
876  return -1;
877  }
878  InterlockedExchange(&win32_ssl_create_mutex, 0);
879  }
880 #endif
881  if (pthread_mutex_lock(&ssl_config_mutex))
882  return -1;
883 
884 #ifdef HAVE_CRYPTO_LOCK
885  if (pq_init_crypto_lib)
886  {
887  /*
888  * If necessary, set up an array to hold locks for libcrypto.
889  * libcrypto will tell us how big to make this array.
890  */
891  if (pq_lockarray == NULL)
892  {
893  int i;
894 
895  pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
896  if (!pq_lockarray)
897  {
898  pthread_mutex_unlock(&ssl_config_mutex);
899  return -1;
900  }
901  for (i = 0; i < CRYPTO_num_locks(); i++)
902  {
903  if (pthread_mutex_init(&pq_lockarray[i], NULL))
904  {
905  free(pq_lockarray);
906  pq_lockarray = NULL;
907  pthread_mutex_unlock(&ssl_config_mutex);
908  return -1;
909  }
910  }
911  }
912 
913  if (ssl_open_connections++ == 0)
914  {
915  /*
916  * These are only required for threaded libcrypto applications,
917  * but make sure we don't stomp on them if they're already set.
918  */
919  if (CRYPTO_get_id_callback() == NULL)
920  CRYPTO_set_id_callback(pq_threadidcallback);
921  if (CRYPTO_get_locking_callback() == NULL)
922  CRYPTO_set_locking_callback(pq_lockingcallback);
923  }
924  }
925 #endif /* HAVE_CRYPTO_LOCK */
926 #endif /* ENABLE_THREAD_SAFETY */
927 
928  if (!ssl_lib_initialized)
929  {
930  if (pq_init_ssl_lib)
931  {
932 #ifdef HAVE_OPENSSL_INIT_SSL
933  OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
934 #else
935  OPENSSL_config(NULL);
936  SSL_library_init();
937  SSL_load_error_strings();
938 #endif
939  }
940  ssl_lib_initialized = true;
941  }
942 
943 #ifdef ENABLE_THREAD_SAFETY
944  pthread_mutex_unlock(&ssl_config_mutex);
945 #endif
946  return 0;
947 }
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 106 of file fe-secure-openssl.c.

References pq_init_crypto_lib, and pq_init_ssl_lib.

Referenced by PQinitOpenSSL(), and PQinitSSL().

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  if (ssl_open_connections != 0)
115  return;
116 #endif
117 
118  pq_init_ssl_lib = do_ssl;
119  pq_init_crypto_lib = do_crypto;
120 }
static bool pq_init_ssl_lib
static bool pq_init_crypto_lib

◆ pgtls_open_client()

PostgresPollingStatusType pgtls_open_client ( PGconn conn)

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

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

Referenced by pqsecure_open_client().

127 {
128  /* First time through? */
129  if (conn->ssl == NULL)
130  {
131  /*
132  * Create a connection-specific SSL object, and load client
133  * certificate, private key, and trusted CA certs.
134  */
135  if (initialize_SSL(conn) != 0)
136  {
137  /* initialize_SSL already put a message in conn->errorMessage */
138  pgtls_close(conn);
139  return PGRES_POLLING_FAILED;
140  }
141  }
142 
143  /* Begin or continue the actual handshake */
144  return open_client_SSL(conn);
145 }
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 164 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().

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

◆ pgtls_read_pending()

bool pgtls_read_pending ( PGconn conn)

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

Referenced by pqSocketCheck().

152 {
153  return SSL_pending(conn->ssl);
154 }

◆ pgtls_write()

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

Definition at line 295 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().

296 {
297  ssize_t n;
298  int result_errno = 0;
299  char sebuf[256];
300  int err;
301  unsigned long ecode;
302 
303  SOCK_ERRNO_SET(0);
304  ERR_clear_error();
305  n = SSL_write(conn->ssl, ptr, len);
306  err = SSL_get_error(conn->ssl, n);
307  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
308  switch (err)
309  {
310  case SSL_ERROR_NONE:
311  if (n < 0)
312  {
313  /* Not supposed to happen, so we don't translate the msg */
315  "SSL_write failed but did not provide error information\n");
316  /* assume the connection is broken */
317  result_errno = ECONNRESET;
318  }
319  break;
320  case SSL_ERROR_WANT_READ:
321 
322  /*
323  * Returning 0 here causes caller to wait for write-ready, which
324  * is not really the right thing, but it's the best we can do.
325  */
326  n = 0;
327  break;
328  case SSL_ERROR_WANT_WRITE:
329  n = 0;
330  break;
331  case SSL_ERROR_SYSCALL:
332  if (n < 0)
333  {
334  result_errno = SOCK_ERRNO;
335  if (result_errno == EPIPE || result_errno == ECONNRESET)
338  "server closed the connection unexpectedly\n"
339  "\tThis probably means the server terminated abnormally\n"
340  "\tbefore or while processing the request.\n"));
341  else
343  libpq_gettext("SSL SYSCALL error: %s\n"),
344  SOCK_STRERROR(result_errno,
345  sebuf, sizeof(sebuf)));
346  }
347  else
348  {
350  libpq_gettext("SSL SYSCALL error: EOF detected\n"));
351  /* assume the connection is broken */
352  result_errno = ECONNRESET;
353  n = -1;
354  }
355  break;
356  case SSL_ERROR_SSL:
357  {
358  char *errm = SSLerrmessage(ecode);
359 
361  libpq_gettext("SSL error: %s\n"), errm);
362  SSLerrfree(errm);
363  /* assume the connection is broken */
364  result_errno = ECONNRESET;
365  n = -1;
366  break;
367  }
368  case SSL_ERROR_ZERO_RETURN:
369 
370  /*
371  * Per OpenSSL documentation, this error code is only returned for
372  * a clean connection closure, so we should not report it as a
373  * server crash.
374  */
376  libpq_gettext("SSL connection has been closed unexpectedly\n"));
377  result_errno = ECONNRESET;
378  n = -1;
379  break;
380  default:
382  libpq_gettext("unrecognized SSL error code: %d\n"),
383  err);
384  /* assume the connection is broken */
385  result_errno = ECONNRESET;
386  n = -1;
387  break;
388  }
389 
390  /* ensure we return the intended errno to caller */
391  SOCK_ERRNO_SET(result_errno);
392 
393  return n;
394 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define SOCK_STRERROR
Definition: libpq-int.h:701
#define SOCK_ERRNO
Definition: libpq-int.h:700
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:702
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:687

◆ PQgetssl()

void* PQgetssl ( PGconn conn)

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

1608 {
1609  if (!conn)
1610  return NULL;
1611  return conn->ssl;
1612 }

◆ PQsslAttribute()

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

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

Referenced by printSSLInfo().

1641 {
1642  if (!conn)
1643  return NULL;
1644  if (conn->ssl == NULL)
1645  return NULL;
1646 
1647  if (strcmp(attribute_name, "library") == 0)
1648  return "OpenSSL";
1649 
1650  if (strcmp(attribute_name, "key_bits") == 0)
1651  {
1652  static char sslbits_str[10];
1653  int sslbits;
1654 
1655  SSL_get_cipher_bits(conn->ssl, &sslbits);
1656  snprintf(sslbits_str, sizeof(sslbits_str), "%d", sslbits);
1657  return sslbits_str;
1658  }
1659 
1660  if (strcmp(attribute_name, "cipher") == 0)
1661  return SSL_get_cipher(conn->ssl);
1662 
1663  if (strcmp(attribute_name, "compression") == 0)
1664  return SSL_get_current_compression(conn->ssl) ? "on" : "off";
1665 
1666  if (strcmp(attribute_name, "protocol") == 0)
1667  return SSL_get_version(conn->ssl);
1668 
1669  return NULL; /* unknown attribute */
1670 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define SSL_get_current_compression(x)
Definition: port.h:387

◆ PQsslAttributeNames()

const char* const* PQsslAttributeNames ( PGconn conn)

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

1626 {
1627  static const char *const result[] = {
1628  "library",
1629  "key_bits",
1630  "cipher",
1631  "compression",
1632  "protocol",
1633  NULL
1634  };
1635 
1636  return result;
1637 }

◆ PQsslInUse()

int PQsslInUse ( PGconn conn)

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

Referenced by printSSLInfo().

1597 {
1598  if (!conn)
1599  return 0;
1600  return conn->ssl_in_use;
1601 }
bool ssl_in_use
Definition: libpq-int.h:458

◆ PQsslStruct()

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

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

1616 {
1617  if (!conn)
1618  return NULL;
1619  if (strcmp(struct_name, "OpenSSL") == 0)
1620  return conn->ssl;
1621  return NULL;
1622 }

◆ SSLerrfree()

static void SSLerrfree ( char *  buf)
static

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

References free, and ssl_nomem.

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

1586 {
1587  if (buf != ssl_nomem)
1588  free(buf);
1589 }
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 1561 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().

1562 {
1563  const char *errreason;
1564  char *errbuf;
1565 
1566  errbuf = malloc(SSL_ERR_LEN);
1567  if (!errbuf)
1568  return ssl_nomem;
1569  if (ecode == 0)
1570  {
1571  snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("no SSL error reported"));
1572  return errbuf;
1573  }
1574  errreason = ERR_reason_error_string(ecode);
1575  if (errreason != NULL)
1576  {
1577  strlcpy(errbuf, errreason, SSL_ERR_LEN);
1578  return errbuf;
1579  }
1580  snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("SSL error code %lu"), ecode);
1581  return errbuf;
1582 }
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:687

◆ verify_cb()

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

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

Referenced by initialize_SSL().

526 {
527  return ok;
528 }

◆ verify_peer_name_matches_certificate()

static bool verify_peer_name_matches_certificate ( PGconn conn)
static

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

References pg_conn::errorMessage, free, i, libpq_gettext, libpq_ngettext, name, PQhost(), printfPQExpBuffer(), pthread_mutex_lock(), pthread_mutex_unlock(), pthread_self(), pg_conn::sslmode, and verify_peer_name_matches_certificate_name().

Referenced by open_client_SSL().

671 {
672  int names_examined = 0;
673  bool found_match = false;
674  bool got_error = false;
675  char *first_name = NULL;
676 
677  STACK_OF(GENERAL_NAME) *peer_san;
678  int i;
679  int rc;
680  char *host = PQhost(conn);
681 
682  /*
683  * If told not to verify the peer name, don't do it. Return true
684  * indicating that the verification was successful.
685  */
686  if (strcmp(conn->sslmode, "verify-full") != 0)
687  return true;
688 
689  /* Check that we have a hostname to compare with. */
690  if (!(host && host[0] != '\0'))
691  {
693  libpq_gettext("host name must be specified for a verified SSL connection\n"));
694  return false;
695  }
696 
697  /*
698  * First, get the Subject Alternative Names (SANs) from the certificate,
699  * and compare them against the originally given hostname.
700  */
701  peer_san = (STACK_OF(GENERAL_NAME) *)
702  X509_get_ext_d2i(conn->peer, NID_subject_alt_name, NULL, NULL);
703 
704  if (peer_san)
705  {
706  int san_len = sk_GENERAL_NAME_num(peer_san);
707 
708  for (i = 0; i < san_len; i++)
709  {
710  const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i);
711 
712  if (name->type == GEN_DNS)
713  {
714  char *alt_name;
715 
716  names_examined++;
718  name->d.dNSName,
719  &alt_name);
720  if (rc == -1)
721  got_error = true;
722  if (rc == 1)
723  found_match = true;
724 
725  if (alt_name)
726  {
727  if (!first_name)
728  first_name = alt_name;
729  else
730  free(alt_name);
731  }
732  }
733  if (found_match || got_error)
734  break;
735  }
736  sk_GENERAL_NAME_free(peer_san);
737  }
738 
739  /*
740  * If there is no subjectAltName extension of type dNSName, check the
741  * Common Name.
742  *
743  * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
744  * dNSName is present, the CN must be ignored.)
745  */
746  if (names_examined == 0)
747  {
748  X509_NAME *subject_name;
749 
750  subject_name = X509_get_subject_name(conn->peer);
751  if (subject_name != NULL)
752  {
753  int cn_index;
754 
755  cn_index = X509_NAME_get_index_by_NID(subject_name,
756  NID_commonName, -1);
757  if (cn_index >= 0)
758  {
759  names_examined++;
761  conn,
762  X509_NAME_ENTRY_get_data(
763  X509_NAME_get_entry(subject_name, cn_index)),
764  &first_name);
765 
766  if (rc == -1)
767  got_error = true;
768  else if (rc == 1)
769  found_match = true;
770  }
771  }
772  }
773 
774  if (!found_match && !got_error)
775  {
776  /*
777  * No match. Include the name from the server certificate in the error
778  * message, to aid debugging broken configurations. If there are
779  * multiple names, only print the first one to avoid an overly long
780  * error message.
781  */
782  if (names_examined > 1)
783  {
785  libpq_ngettext("server certificate for \"%s\" (and %d other name) does not match host name \"%s\"\n",
786  "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"\n",
787  names_examined - 1),
788  first_name, names_examined - 1, host);
789  }
790  else if (names_examined == 1)
791  {
793  libpq_gettext("server certificate for \"%s\" does not match host name \"%s\"\n"),
794  first_name, host);
795  }
796  else
797  {
799  libpq_gettext("could not get server's host name from server certificate\n"));
800  }
801  }
802 
803  /* clean up */
804  if (first_name)
805  free(first_name);
806 
807  return found_match && !got_error;
808 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define libpq_ngettext(s, p, n)
Definition: libpq-int.h:688
char * sslmode
Definition: libpq-int.h:353
PQExpBufferData errorMessage
Definition: libpq-int.h:494
char * PQhost(const PGconn *conn)
Definition: fe-connect.c:6016
#define free(a)
Definition: header.h:65
const char * name
Definition: encode.c:521
static int verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *name, char **store_name)
int i
#define libpq_gettext(x)
Definition: libpq-int.h:687

◆ verify_peer_name_matches_certificate_name()

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

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

References pg_conn::errorMessage, free, libpq_gettext, malloc, name, pg_strcasecmp(), PQhost(), printfPQExpBuffer(), and wildcard_certificate_match().

Referenced by verify_peer_name_matches_certificate().

594 {
595  int len;
596  char *name;
597  const unsigned char *namedata;
598  int result;
599  char *host = PQhost(conn);
600 
601  *store_name = NULL;
602 
603  /* Should not happen... */
604  if (name_entry == NULL)
605  {
607  libpq_gettext("SSL certificate's name entry is missing\n"));
608  return -1;
609  }
610 
611  /*
612  * GEN_DNS can be only IA5String, equivalent to US ASCII.
613  *
614  * There is no guarantee the string returned from the certificate is
615  * NULL-terminated, so make a copy that is.
616  */
617 #ifdef HAVE_ASN1_STRING_GET0_DATA
618  namedata = ASN1_STRING_get0_data(name_entry);
619 #else
620  namedata = ASN1_STRING_data(name_entry);
621 #endif
622  len = ASN1_STRING_length(name_entry);
623  name = malloc(len + 1);
624  if (name == NULL)
625  {
627  libpq_gettext("out of memory\n"));
628  return -1;
629  }
630  memcpy(name, namedata, len);
631  name[len] = '\0';
632 
633  /*
634  * Reject embedded NULLs in certificate common or alternative name to
635  * prevent attacks like CVE-2009-4034.
636  */
637  if (len != strlen(name))
638  {
639  free(name);
641  libpq_gettext("SSL certificate's name contains embedded null\n"));
642  return -1;
643  }
644 
645  if (pg_strcasecmp(name, host) == 0)
646  {
647  /* Exact name match */
648  result = 1;
649  }
650  else if (wildcard_certificate_match(name, host))
651  {
652  /* Matched wildcard name */
653  result = 1;
654  }
655  else
656  {
657  result = 0;
658  }
659 
660  *store_name = name;
661  return result;
662 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define malloc(a)
Definition: header.h:50
PQExpBufferData errorMessage
Definition: libpq-int.h:494
char * PQhost(const PGconn *conn)
Definition: fe-connect.c:6016
#define free(a)
Definition: header.h:65
const char * name
Definition: encode.c:521
static int wildcard_certificate_match(const char *pattern, const char *string)
#define libpq_gettext(x)
Definition: libpq-int.h:687

◆ wildcard_certificate_match()

static int wildcard_certificate_match ( const char *  pattern,
const char *  string 
)
static

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

References pg_strcasecmp().

Referenced by verify_peer_name_matches_certificate_name().

548 {
549  int lenpat = strlen(pattern);
550  int lenstr = strlen(string);
551 
552  /* If we don't start with a wildcard, it's not a match (rule 1 & 2) */
553  if (lenpat < 3 ||
554  pattern[0] != '*' ||
555  pattern[1] != '.')
556  return 0;
557 
558  if (lenpat > lenstr)
559  /* If pattern is longer than the string, we can never match */
560  return 0;
561 
562  if (pg_strcasecmp(pattern + 1, string + lenstr - lenpat + 1) != 0)
563 
564  /*
565  * If string does not end in pattern (minus the wildcard), we don't
566  * match
567  */
568  return 0;
569 
570  if (strchr(string, '.') < string + lenstr - lenpat)
571 
572  /*
573  * If there is a dot left of where the pattern started to match, we
574  * don't match (rule 3)
575  */
576  return 0;
577 
578  /* String ended with pattern, and didn't have a dot before, so we match */
579  return 1;
580 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36

Variable Documentation

◆ my_bio_methods

BIO_METHOD* my_bio_methods
static

Definition at line 1688 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 1556 of file fe-secure-openssl.c.

Referenced by SSLerrfree(), and SSLerrmessage().