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 "common/openssl.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 PQssl_passwd_cb (char *buf, int size, int rwflag, void *userdata)
 
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)
 
static int ssl_protocol_version_to_openssl (const char *protocol)
 
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)
 
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)
 
int PQdefaultSSLKeyPassHook (char *buf, int size, PGconn *conn)
 
PQsslKeyPassHook_type PQgetSSLKeyPassHook (void)
 
void PQsetSSLKeyPassHook (PQsslKeyPassHook_type hook)
 

Variables

static bool pq_init_ssl_lib = true
 
static bool pq_init_crypto_lib = true
 
static bool ssl_lib_initialized = false
 
static PQsslKeyPassHook_type PQsslKeyPassHook = NULL
 
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 1527 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 1528 of file fe-secure-openssl.c.

Referenced by my_SSL_set_fd().

◆ SSL_ERR_LEN

#define SSL_ERR_LEN   128

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

Referenced by SSLerrmessage().

Function Documentation

◆ destroy_ssl_system()

static void destroy_ssl_system ( void  )
static

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

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

Referenced by pgtls_close().

737 {
738 #if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK)
739  /* Mutex is created in pgtls_init() */
740  if (pthread_mutex_lock(&ssl_config_mutex))
741  return;
742 
743  if (pq_init_crypto_lib && ssl_open_connections > 0)
744  --ssl_open_connections;
745 
746  if (pq_init_crypto_lib && ssl_open_connections == 0)
747  {
748  /*
749  * No connections left, unregister libcrypto callbacks, if no one
750  * registered different ones in the meantime.
751  */
752  if (CRYPTO_get_locking_callback() == pq_lockingcallback)
753  CRYPTO_set_locking_callback(NULL);
754  if (CRYPTO_get_id_callback() == pq_threadidcallback)
755  CRYPTO_set_id_callback(NULL);
756 
757  /*
758  * We don't free the lock array. If we get another connection in this
759  * process, we will just re-use them with the existing mutexes.
760  *
761  * This means we leak a little memory on repeated load/unload of the
762  * library.
763  */
764  }
765 
766  pthread_mutex_unlock(&ssl_config_mutex);
767 #endif
768 }
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 777 of file fe-secure-openssl.c.

References pg_conn::errorMessage, free, libpq_gettext, MAXPGPATH, my_SSL_set_fd(), PG_STRERROR_R_BUFLEN, pqGetHomeDirectory(), PQssl_passwd_cb(), PQsslKeyPassHook, printfPQExpBuffer(), S_IRWXG, S_IRWXO, S_ISREG, snprintf, pg_conn::sock, SSL_context, SSL_CTX_set_max_proto_version(), SSL_CTX_set_min_proto_version(), pg_conn::ssl_in_use, ssl_protocol_version_to_openssl(), pg_conn::sslcert, pg_conn::sslcompression, pg_conn::sslcrl, SSLerrfree(), SSLerrmessage(), pg_conn::sslkey, pg_conn::sslmaxprotocolversion, pg_conn::sslminprotocolversion, pg_conn::sslmode, pg_conn::sslpassword, pg_conn::sslrootcert, stat, strerror_r, strlcpy(), and verify_cb().

Referenced by pgtls_open_client().

778 {
779  SSL_CTX *SSL_context;
780  struct stat buf;
781  char homedir[MAXPGPATH];
782  char fnbuf[MAXPGPATH];
783  char sebuf[PG_STRERROR_R_BUFLEN];
784  bool have_homedir;
785  bool have_cert;
786  bool have_rootcert;
787  EVP_PKEY *pkey = NULL;
788 
789  /*
790  * We'll need the home directory if any of the relevant parameters are
791  * defaulted. If pqGetHomeDirectory fails, act as though none of the
792  * files could be found.
793  */
794  if (!(conn->sslcert && strlen(conn->sslcert) > 0) ||
795  !(conn->sslkey && strlen(conn->sslkey) > 0) ||
796  !(conn->sslrootcert && strlen(conn->sslrootcert) > 0) ||
797  !(conn->sslcrl && strlen(conn->sslcrl) > 0))
798  have_homedir = pqGetHomeDirectory(homedir, sizeof(homedir));
799  else /* won't need it */
800  have_homedir = false;
801 
802  /*
803  * Create a new SSL_CTX object.
804  *
805  * We used to share a single SSL_CTX between all connections, but it was
806  * complicated if connections used different certificates. So now we
807  * create a separate context for each connection, and accept the overhead.
808  */
809  SSL_context = SSL_CTX_new(SSLv23_method());
810  if (!SSL_context)
811  {
812  char *err = SSLerrmessage(ERR_get_error());
813 
815  libpq_gettext("could not create SSL context: %s\n"),
816  err);
817  SSLerrfree(err);
818  return -1;
819  }
820 
821  /*
822  * Delegate the client cert password prompt to the libpq wrapper
823  * callback if any is defined.
824  *
825  * If the application hasn't installed its own and the sslpassword
826  * parameter is non-null, we install ours now to make sure we
827  * supply PGconn->sslpassword to OpenSSL instead of letting it
828  * prompt on stdin.
829  *
830  * This will replace OpenSSL's default PEM_def_callback (which
831  * prompts on stdin), but we're only setting it for this SSL
832  * context so it's harmless.
833  */
834  if (PQsslKeyPassHook
835  || (conn->sslpassword && strlen(conn->sslpassword) > 0))
836  {
837  SSL_CTX_set_default_passwd_cb(SSL_context, PQssl_passwd_cb);
838  SSL_CTX_set_default_passwd_cb_userdata(SSL_context, conn);
839  }
840 
841  /* Disable old protocol versions */
842  SSL_CTX_set_options(SSL_context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
843 
844  /* Set the minimum and maximum protocol versions if necessary */
845  if (conn->sslminprotocolversion &&
846  strlen(conn->sslminprotocolversion) != 0)
847  {
848  int ssl_min_ver;
849 
851 
852  if (ssl_min_ver == -1)
853  {
855  libpq_gettext("invalid value \"%s\" for minimum version of SSL protocol\n"),
856  conn->sslminprotocolversion);
857  SSL_CTX_free(SSL_context);
858  return -1;
859  }
860 
861  if (!SSL_CTX_set_min_proto_version(SSL_context, ssl_min_ver))
862  {
863  char *err = SSLerrmessage(ERR_get_error());
864 
866  libpq_gettext("could not set minimum version of SSL protocol: %s\n"),
867  err);
868  SSLerrfree(err);
869  SSL_CTX_free(SSL_context);
870  return -1;
871  }
872  }
873 
874  if (conn->sslmaxprotocolversion &&
875  strlen(conn->sslmaxprotocolversion) != 0)
876  {
877  int ssl_max_ver;
878 
880 
881  if (ssl_max_ver == -1)
882  {
884  libpq_gettext("invalid value \"%s\" for maximum version of SSL protocol\n"),
885  conn->sslmaxprotocolversion);
886  SSL_CTX_free(SSL_context);
887  return -1;
888  }
889 
890  if (!SSL_CTX_set_max_proto_version(SSL_context, ssl_max_ver))
891  {
892  char *err = SSLerrmessage(ERR_get_error());
893 
895  libpq_gettext("could not set maximum version of SSL protocol: %s\n"),
896  err);
897  SSLerrfree(err);
898  SSL_CTX_free(SSL_context);
899  return -1;
900  }
901  }
902 
903  /*
904  * Disable OpenSSL's moving-write-buffer sanity check, because it causes
905  * unnecessary failures in nonblocking send cases.
906  */
907  SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
908 
909  /*
910  * If the root cert file exists, load it so we can perform certificate
911  * verification. If sslmode is "verify-full" we will also do further
912  * verification after the connection has been completed.
913  */
914  if (conn->sslrootcert && strlen(conn->sslrootcert) > 0)
915  strlcpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
916  else if (have_homedir)
917  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
918  else
919  fnbuf[0] = '\0';
920 
921  if (fnbuf[0] != '\0' &&
922  stat(fnbuf, &buf) == 0)
923  {
924  X509_STORE *cvstore;
925 
926  if (SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL) != 1)
927  {
928  char *err = SSLerrmessage(ERR_get_error());
929 
931  libpq_gettext("could not read root certificate file \"%s\": %s\n"),
932  fnbuf, err);
933  SSLerrfree(err);
934  SSL_CTX_free(SSL_context);
935  return -1;
936  }
937 
938  if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
939  {
940  if (conn->sslcrl && strlen(conn->sslcrl) > 0)
941  strlcpy(fnbuf, conn->sslcrl, sizeof(fnbuf));
942  else if (have_homedir)
943  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE);
944  else
945  fnbuf[0] = '\0';
946 
947  /* Set the flags to check against the complete CRL chain */
948  if (fnbuf[0] != '\0' &&
949  X509_STORE_load_locations(cvstore, fnbuf, NULL) == 1)
950  {
951  X509_STORE_set_flags(cvstore,
952  X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
953  }
954  /* if not found, silently ignore; we do not require CRL */
955  ERR_clear_error();
956  }
957  have_rootcert = true;
958  }
959  else
960  {
961  /*
962  * stat() failed; assume root file doesn't exist. If sslmode is
963  * verify-ca or verify-full, this is an error. Otherwise, continue
964  * without performing any server cert verification.
965  */
966  if (conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */
967  {
968  /*
969  * The only way to reach here with an empty filename is if
970  * pqGetHomeDirectory failed. That's a sufficiently unusual case
971  * that it seems worth having a specialized error message for it.
972  */
973  if (fnbuf[0] == '\0')
975  libpq_gettext("could not get home directory to locate root certificate file\n"
976  "Either provide the file or change sslmode to disable server certificate verification.\n"));
977  else
979  libpq_gettext("root certificate file \"%s\" does not exist\n"
980  "Either provide the file or change sslmode to disable server certificate verification.\n"), fnbuf);
981  SSL_CTX_free(SSL_context);
982  return -1;
983  }
984  have_rootcert = false;
985  }
986 
987  /* Read the client certificate file */
988  if (conn->sslcert && strlen(conn->sslcert) > 0)
989  strlcpy(fnbuf, conn->sslcert, sizeof(fnbuf));
990  else if (have_homedir)
991  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
992  else
993  fnbuf[0] = '\0';
994 
995  if (fnbuf[0] == '\0')
996  {
997  /* no home directory, proceed without a client cert */
998  have_cert = false;
999  }
1000  else if (stat(fnbuf, &buf) != 0)
1001  {
1002  /*
1003  * If file is not present, just go on without a client cert; server
1004  * might or might not accept the connection. Any other error,
1005  * however, is grounds for complaint.
1006  */
1007  if (errno != ENOENT && errno != ENOTDIR)
1008  {
1010  libpq_gettext("could not open certificate file \"%s\": %s\n"),
1011  fnbuf, strerror_r(errno, sebuf, sizeof(sebuf)));
1012  SSL_CTX_free(SSL_context);
1013  return -1;
1014  }
1015  have_cert = false;
1016  }
1017  else
1018  {
1019  /*
1020  * Cert file exists, so load it. Since OpenSSL doesn't provide the
1021  * equivalent of "SSL_use_certificate_chain_file", we have to load it
1022  * into the SSL context, rather than the SSL object.
1023  */
1024  if (SSL_CTX_use_certificate_chain_file(SSL_context, fnbuf) != 1)
1025  {
1026  char *err = SSLerrmessage(ERR_get_error());
1027 
1029  libpq_gettext("could not read certificate file \"%s\": %s\n"),
1030  fnbuf, err);
1031  SSLerrfree(err);
1032  SSL_CTX_free(SSL_context);
1033  return -1;
1034  }
1035 
1036  /* need to load the associated private key, too */
1037  have_cert = true;
1038  }
1039 
1040  /*
1041  * The SSL context is now loaded with the correct root and client
1042  * certificates. Create a connection-specific SSL object. The private key
1043  * is loaded directly into the SSL object. (We could load the private key
1044  * into the context, too, but we have done it this way historically, and
1045  * it doesn't really matter.)
1046  */
1047  if (!(conn->ssl = SSL_new(SSL_context)) ||
1048  !SSL_set_app_data(conn->ssl, conn) ||
1049  !my_SSL_set_fd(conn, conn->sock))
1050  {
1051  char *err = SSLerrmessage(ERR_get_error());
1052 
1054  libpq_gettext("could not establish SSL connection: %s\n"),
1055  err);
1056  SSLerrfree(err);
1057  SSL_CTX_free(SSL_context);
1058  return -1;
1059  }
1060  conn->ssl_in_use = true;
1061 
1062  /*
1063  * SSL contexts are reference counted by OpenSSL. We can free it as soon
1064  * as we have created the SSL object, and it will stick around for as long
1065  * as it's actually needed.
1066  */
1067  SSL_CTX_free(SSL_context);
1068  SSL_context = NULL;
1069 
1070  /*
1071  * Read the SSL key. If a key is specified, treat it as an engine:key
1072  * combination if there is colon present - we don't support files with
1073  * colon in the name. The exception is if the second character is a colon,
1074  * in which case it can be a Windows filename with drive specification.
1075  */
1076  if (have_cert && conn->sslkey && strlen(conn->sslkey) > 0)
1077  {
1078 #ifdef USE_SSL_ENGINE
1079  if (strchr(conn->sslkey, ':')
1080 #ifdef WIN32
1081  && conn->sslkey[1] != ':'
1082 #endif
1083  )
1084  {
1085  /* Colon, but not in second character, treat as engine:key */
1086  char *engine_str = strdup(conn->sslkey);
1087  char *engine_colon;
1088 
1089  if (engine_str == NULL)
1090  {
1092  libpq_gettext("out of memory\n"));
1093  return -1;
1094  }
1095 
1096  /* cannot return NULL because we already checked before strdup */
1097  engine_colon = strchr(engine_str, ':');
1098 
1099  *engine_colon = '\0'; /* engine_str now has engine name */
1100  engine_colon++; /* engine_colon now has key name */
1101 
1102  conn->engine = ENGINE_by_id(engine_str);
1103  if (conn->engine == NULL)
1104  {
1105  char *err = SSLerrmessage(ERR_get_error());
1106 
1108  libpq_gettext("could not load SSL engine \"%s\": %s\n"),
1109  engine_str, err);
1110  SSLerrfree(err);
1111  free(engine_str);
1112  return -1;
1113  }
1114 
1115  if (ENGINE_init(conn->engine) == 0)
1116  {
1117  char *err = SSLerrmessage(ERR_get_error());
1118 
1120  libpq_gettext("could not initialize SSL engine \"%s\": %s\n"),
1121  engine_str, err);
1122  SSLerrfree(err);
1123  ENGINE_free(conn->engine);
1124  conn->engine = NULL;
1125  free(engine_str);
1126  return -1;
1127  }
1128 
1129  pkey = ENGINE_load_private_key(conn->engine, engine_colon,
1130  NULL, NULL);
1131  if (pkey == NULL)
1132  {
1133  char *err = SSLerrmessage(ERR_get_error());
1134 
1136  libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"),
1137  engine_colon, engine_str, err);
1138  SSLerrfree(err);
1139  ENGINE_finish(conn->engine);
1140  ENGINE_free(conn->engine);
1141  conn->engine = NULL;
1142  free(engine_str);
1143  return -1;
1144  }
1145  if (SSL_use_PrivateKey(conn->ssl, pkey) != 1)
1146  {
1147  char *err = SSLerrmessage(ERR_get_error());
1148 
1150  libpq_gettext("could not load private SSL key \"%s\" from engine \"%s\": %s\n"),
1151  engine_colon, engine_str, err);
1152  SSLerrfree(err);
1153  ENGINE_finish(conn->engine);
1154  ENGINE_free(conn->engine);
1155  conn->engine = NULL;
1156  free(engine_str);
1157  return -1;
1158  }
1159 
1160  free(engine_str);
1161 
1162  fnbuf[0] = '\0'; /* indicate we're not going to load from a
1163  * file */
1164  }
1165  else
1166 #endif /* USE_SSL_ENGINE */
1167  {
1168  /* PGSSLKEY is not an engine, treat it as a filename */
1169  strlcpy(fnbuf, conn->sslkey, sizeof(fnbuf));
1170  }
1171  }
1172  else if (have_homedir)
1173  {
1174  /* No PGSSLKEY specified, load default file */
1175  snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
1176  }
1177  else
1178  fnbuf[0] = '\0';
1179 
1180  if (have_cert && fnbuf[0] != '\0')
1181  {
1182  /* read the client key from file */
1183 
1184  if (stat(fnbuf, &buf) != 0)
1185  {
1187  libpq_gettext("certificate present, but not private key file \"%s\"\n"),
1188  fnbuf);
1189  return -1;
1190  }
1191 #ifndef WIN32
1192  if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
1193  {
1195  libpq_gettext("private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
1196  fnbuf);
1197  return -1;
1198  }
1199 #endif
1200 
1201  if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_PEM) != 1)
1202  {
1203  char *err = SSLerrmessage(ERR_get_error());
1204 
1205  /*
1206  * We'll try to load the file in DER (binary ASN.1) format, and if
1207  * that fails too, report the original error. This could mask
1208  * issues where there's something wrong with a DER-format cert, but
1209  * we'd have to duplicate openssl's format detection to be smarter
1210  * than this. We can't just probe for a leading -----BEGIN because
1211  * PEM can have leading non-matching lines and blanks. OpenSSL
1212  * doesn't expose its get_name(...) and its PEM routines don't
1213  * differentiate between failure modes in enough detail to let us
1214  * tell the difference between "not PEM, try DER" and "wrong
1215  * password".
1216  */
1217  if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_ASN1) != 1)
1218  {
1220  libpq_gettext("could not load private key file \"%s\": %s\n"),
1221  fnbuf, err);
1222  SSLerrfree(err);
1223  return -1;
1224  }
1225 
1226  SSLerrfree(err);
1227 
1228  }
1229  }
1230 
1231  /* verify that the cert and key go together */
1232  if (have_cert &&
1233  SSL_check_private_key(conn->ssl) != 1)
1234  {
1235  char *err = SSLerrmessage(ERR_get_error());
1236 
1238  libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
1239  fnbuf, err);
1240  SSLerrfree(err);
1241  return -1;
1242  }
1243 
1244  /*
1245  * If a root cert was loaded, also set our certificate verification
1246  * callback.
1247  */
1248  if (have_rootcert)
1249  SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, verify_cb);
1250 
1251  /*
1252  * Set compression option if necessary.
1253  */
1254  if (conn->sslcompression && conn->sslcompression[0] == '0')
1255  SSL_set_options(conn->ssl, SSL_OP_NO_COMPRESSION);
1256  else
1257  SSL_clear_options(conn->ssl, SSL_OP_NO_COMPRESSION);
1258 
1259  return 0;
1260 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define PG_STRERROR_R_BUFLEN
Definition: port.h:211
char * sslminprotocolversion
Definition: libpq-int.h:370
static int PQssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
char * sslkey
Definition: libpq-int.h:360
char * sslcompression
Definition: libpq-int.h:359
#define MAXPGPATH
bool ssl_in_use
Definition: libpq-int.h:472
char * sslmaxprotocolversion
Definition: libpq-int.h:371
static char * buf
Definition: pg_test_fsync.c:67
#define S_IRWXG
Definition: win32_port.h:281
char * sslpassword
Definition: libpq-int.h:362
static PQsslKeyPassHook_type PQsslKeyPassHook
static int verify_cb(int ok, X509_STORE_CTX *ctx)
pgsocket sock
Definition: libpq-int.h:410
#define S_ISREG(m)
Definition: win32_port.h:299
static int my_SSL_set_fd(PGconn *conn, int fd)
static void SSLerrfree(char *buf)
#define stat(a, b)
Definition: win32_port.h:255
char * sslmode
Definition: libpq-int.h:358
PQExpBufferData errorMessage
Definition: libpq-int.h:526
char * sslcert
Definition: libpq-int.h:361
#define free(a)
Definition: header.h:65
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
static int ssl_protocol_version_to_openssl(const char *protocol)
#define strerror_r
Definition: port.h:210
char * sslrootcert
Definition: libpq-int.h:363
static char * SSLerrmessage(unsigned long ecode)
static SSL_CTX * SSL_context
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7205
int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
#define snprintf
Definition: port.h:193
char * sslcrl
Definition: libpq-int.h:364
#define S_IRWXO
Definition: win32_port.h:293
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ my_BIO_s_socket()

static BIO_METHOD * my_BIO_s_socket ( void  )
static

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

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

Referenced by my_SSL_set_fd().

1595 {
1596  if (!my_bio_methods)
1597  {
1598  BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
1599 #ifdef HAVE_BIO_METH_NEW
1600  int my_bio_index;
1601 
1602  my_bio_index = BIO_get_new_index();
1603  if (my_bio_index == -1)
1604  return NULL;
1605  my_bio_methods = BIO_meth_new(my_bio_index, "libpq socket");
1606  if (!my_bio_methods)
1607  return NULL;
1608 
1609  /*
1610  * As of this writing, these functions never fail. But check anyway,
1611  * like OpenSSL's own examples do.
1612  */
1613  if (!BIO_meth_set_write(my_bio_methods, my_sock_write) ||
1614  !BIO_meth_set_read(my_bio_methods, my_sock_read) ||
1615  !BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) ||
1616  !BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) ||
1617  !BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) ||
1618  !BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) ||
1619  !BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) ||
1620  !BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom)))
1621  {
1622  BIO_meth_free(my_bio_methods);
1623  my_bio_methods = NULL;
1624  return NULL;
1625  }
1626 #else
1627  my_bio_methods = malloc(sizeof(BIO_METHOD));
1628  if (!my_bio_methods)
1629  return NULL;
1630  memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
1631  my_bio_methods->bread = my_sock_read;
1632  my_bio_methods->bwrite = my_sock_write;
1633 #endif
1634  }
1635  return my_bio_methods;
1636 }
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 1534 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().

1535 {
1536  int res;
1537 
1538  res = pqsecure_raw_read((PGconn *) BIO_get_data(h), buf, size);
1539  BIO_clear_retry_flags(h);
1540  if (res < 0)
1541  {
1542  /* If we were interrupted, tell caller to retry */
1543  switch (SOCK_ERRNO)
1544  {
1545 #ifdef EAGAIN
1546  case EAGAIN:
1547 #endif
1548 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
1549  case EWOULDBLOCK:
1550 #endif
1551  case EINTR:
1552  BIO_set_retry_read(h);
1553  break;
1554 
1555  default:
1556  break;
1557  }
1558  }
1559 
1560  return res;
1561 }
#define EAGAIN
Definition: win32_port.h:321
ssize_t pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
Definition: fe-secure.c:239
#define SOCK_ERRNO
Definition: libpq-int.h:818
static char * buf
Definition: pg_test_fsync.c:67
#define EWOULDBLOCK
Definition: win32_port.h:329
#define EINTR
Definition: win32_port.h:323
#define BIO_get_data(bio)

◆ my_sock_write()

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

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

1565 {
1566  int res;
1567 
1568  res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
1569  BIO_clear_retry_flags(h);
1570  if (res <= 0)
1571  {
1572  /* If we were interrupted, tell caller to retry */
1573  switch (SOCK_ERRNO)
1574  {
1575 #ifdef EAGAIN
1576  case EAGAIN:
1577 #endif
1578 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
1579  case EWOULDBLOCK:
1580 #endif
1581  case EINTR:
1582  BIO_set_retry_write(h);
1583  break;
1584 
1585  default:
1586  break;
1587  }
1588  }
1589 
1590  return res;
1591 }
#define EAGAIN
Definition: win32_port.h:321
#define SOCK_ERRNO
Definition: libpq-int.h:818
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:322
#define EWOULDBLOCK
Definition: win32_port.h:329
#define EINTR
Definition: win32_port.h:323
#define BIO_get_data(bio)

◆ my_SSL_set_fd()

static int my_SSL_set_fd ( PGconn conn,
int  fd 
)
static

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

References BIO_set_data, and my_BIO_s_socket().

Referenced by initialize_SSL().

1641 {
1642  int ret = 0;
1643  BIO *bio;
1644  BIO_METHOD *bio_method;
1645 
1646  bio_method = my_BIO_s_socket();
1647  if (bio_method == NULL)
1648  {
1649  SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
1650  goto err;
1651  }
1652  bio = BIO_new(bio_method);
1653  if (bio == NULL)
1654  {
1655  SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
1656  goto err;
1657  }
1658  BIO_set_data(bio, conn);
1659 
1660  SSL_set_bio(conn->ssl, bio, bio);
1661  BIO_set_fd(bio, fd, BIO_NOCLOSE);
1662  ret = 1;
1663 err:
1664  return ret;
1665 }
#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 1266 of file fe-secure-openssl.c.

References pg_conn::errorMessage, libpq_gettext, PG_STRERROR_R_BUFLEN, 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().

1267 {
1268  int r;
1269 
1270  ERR_clear_error();
1271  r = SSL_connect(conn->ssl);
1272  if (r <= 0)
1273  {
1274  int err = SSL_get_error(conn->ssl, r);
1275  unsigned long ecode;
1276 
1277  ecode = ERR_get_error();
1278  switch (err)
1279  {
1280  case SSL_ERROR_WANT_READ:
1281  return PGRES_POLLING_READING;
1282 
1283  case SSL_ERROR_WANT_WRITE:
1284  return PGRES_POLLING_WRITING;
1285 
1286  case SSL_ERROR_SYSCALL:
1287  {
1288  char sebuf[PG_STRERROR_R_BUFLEN];
1289 
1290  if (r == -1)
1292  libpq_gettext("SSL SYSCALL error: %s\n"),
1293  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1294  else
1296  libpq_gettext("SSL SYSCALL error: EOF detected\n"));
1297  pgtls_close(conn);
1298  return PGRES_POLLING_FAILED;
1299  }
1300  case SSL_ERROR_SSL:
1301  {
1302  char *err = SSLerrmessage(ecode);
1303 
1305  libpq_gettext("SSL error: %s\n"),
1306  err);
1307  SSLerrfree(err);
1308  pgtls_close(conn);
1309  return PGRES_POLLING_FAILED;
1310  }
1311 
1312  default:
1314  libpq_gettext("unrecognized SSL error code: %d\n"),
1315  err);
1316  pgtls_close(conn);
1317  return PGRES_POLLING_FAILED;
1318  }
1319  }
1320 
1321  /*
1322  * We already checked the server certificate in initialize_SSL() using
1323  * SSL_CTX_set_verify(), if root.crt exists.
1324  */
1325 
1326  /* get server certificate */
1327  conn->peer = SSL_get_peer_certificate(conn->ssl);
1328  if (conn->peer == NULL)
1329  {
1330  char *err = SSLerrmessage(ERR_get_error());
1331 
1333  libpq_gettext("certificate could not be obtained: %s\n"),
1334  err);
1335  SSLerrfree(err);
1336  pgtls_close(conn);
1337  return PGRES_POLLING_FAILED;
1338  }
1339 
1341  {
1342  pgtls_close(conn);
1343  return PGRES_POLLING_FAILED;
1344  }
1345 
1346  /* SSL handshake is complete */
1347  return PGRES_POLLING_OK;
1348 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define PG_STRERROR_R_BUFLEN
Definition: port.h:211
#define SOCK_STRERROR
Definition: libpq-int.h:819
#define SOCK_ERRNO
Definition: libpq-int.h:818
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:526
static char * SSLerrmessage(unsigned long ecode)
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ 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 478 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().

480 {
481  int len;
482  const unsigned char *namedata;
483 
484  /* Should not happen... */
485  if (name_entry == NULL)
486  {
488  libpq_gettext("SSL certificate's name entry is missing\n"));
489  return -1;
490  }
491 
492  /*
493  * GEN_DNS can be only IA5String, equivalent to US ASCII.
494  */
495 #ifdef HAVE_ASN1_STRING_GET0_DATA
496  namedata = ASN1_STRING_get0_data(name_entry);
497 #else
498  namedata = ASN1_STRING_data(name_entry);
499 #endif
500  len = ASN1_STRING_length(name_entry);
501 
502  /* OK to cast from unsigned to plain char, since it's all ASCII. */
503  return pq_verify_peer_name_matches_certificate_name(conn, (const char *) namedata, len, store_name);
504 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
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:526
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ pgtls_close()

void pgtls_close ( PGconn conn)

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

1352 {
1353  bool destroy_needed = false;
1354 
1355  if (conn->ssl)
1356  {
1357  /*
1358  * We can't destroy everything SSL-related here due to the possible
1359  * later calls to OpenSSL routines which may need our thread
1360  * callbacks, so set a flag here and check at the end.
1361  */
1362  destroy_needed = true;
1363 
1364  SSL_shutdown(conn->ssl);
1365  SSL_free(conn->ssl);
1366  conn->ssl = NULL;
1367  conn->ssl_in_use = false;
1368  }
1369 
1370  if (conn->peer)
1371  {
1372  X509_free(conn->peer);
1373  conn->peer = NULL;
1374  }
1375 
1376 #ifdef USE_SSL_ENGINE
1377  if (conn->engine)
1378  {
1379  ENGINE_finish(conn->engine);
1380  ENGINE_free(conn->engine);
1381  conn->engine = NULL;
1382  }
1383 #endif
1384 
1385  /*
1386  * This will remove our SSL locking hooks, if this is the last SSL
1387  * connection, which means we must wait to call it until after all SSL
1388  * calls have been made, otherwise we can end up with a race condition and
1389  * possible deadlocks.
1390  *
1391  * See comments above destroy_ssl_system().
1392  */
1393  if (destroy_needed)
1395 }
bool ssl_in_use
Definition: libpq-int.h:472
static void destroy_ssl_system(void)

◆ pgtls_init()

int pgtls_init ( PGconn conn)

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

639 {
640 #ifdef ENABLE_THREAD_SAFETY
641 #ifdef WIN32
642  /* Also see similar code in fe-connect.c, default_threadlock() */
643  if (ssl_config_mutex == NULL)
644  {
645  while (InterlockedExchange(&win32_ssl_create_mutex, 1) == 1)
646  /* loop, another thread own the lock */ ;
647  if (ssl_config_mutex == NULL)
648  {
649  if (pthread_mutex_init(&ssl_config_mutex, NULL))
650  return -1;
651  }
652  InterlockedExchange(&win32_ssl_create_mutex, 0);
653  }
654 #endif
655  if (pthread_mutex_lock(&ssl_config_mutex))
656  return -1;
657 
658 #ifdef HAVE_CRYPTO_LOCK
659  if (pq_init_crypto_lib)
660  {
661  /*
662  * If necessary, set up an array to hold locks for libcrypto.
663  * libcrypto will tell us how big to make this array.
664  */
665  if (pq_lockarray == NULL)
666  {
667  int i;
668 
669  pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
670  if (!pq_lockarray)
671  {
672  pthread_mutex_unlock(&ssl_config_mutex);
673  return -1;
674  }
675  for (i = 0; i < CRYPTO_num_locks(); i++)
676  {
677  if (pthread_mutex_init(&pq_lockarray[i], NULL))
678  {
679  free(pq_lockarray);
680  pq_lockarray = NULL;
681  pthread_mutex_unlock(&ssl_config_mutex);
682  return -1;
683  }
684  }
685  }
686 
687  if (ssl_open_connections++ == 0)
688  {
689  /*
690  * These are only required for threaded libcrypto applications,
691  * but make sure we don't stomp on them if they're already set.
692  */
693  if (CRYPTO_get_id_callback() == NULL)
694  CRYPTO_set_id_callback(pq_threadidcallback);
695  if (CRYPTO_get_locking_callback() == NULL)
696  CRYPTO_set_locking_callback(pq_lockingcallback);
697  }
698  }
699 #endif /* HAVE_CRYPTO_LOCK */
700 #endif /* ENABLE_THREAD_SAFETY */
701 
702  if (!ssl_lib_initialized)
703  {
704  if (pq_init_ssl_lib)
705  {
706 #ifdef HAVE_OPENSSL_INIT_SSL
707  OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
708 #else
709  OPENSSL_config(NULL);
710  SSL_library_init();
711  SSL_load_error_strings();
712 #endif
713  }
714  ssl_lib_initialized = true;
715  }
716 
717 #ifdef ENABLE_THREAD_SAFETY
718  pthread_mutex_unlock(&ssl_config_mutex);
719 #endif
720  return 0;
721 }
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 123 of file fe-secure-openssl.c.

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

Referenced by pqsecure_open_client().

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

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

Referenced by pqsecure_read().

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

◆ pgtls_read_pending()

bool pgtls_read_pending ( PGconn conn)

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

Referenced by pqSocketCheck().

269 {
270  return SSL_pending(conn->ssl) > 0;
271 }

◆ 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 512 of file fe-secure-openssl.c.

References free, i, mode, 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().

515 {
516  STACK_OF(GENERAL_NAME) *peer_san;
517  int i;
518  int rc = 0;
519 
520  /*
521  * First, get the Subject Alternative Names (SANs) from the certificate,
522  * and compare them against the originally given hostname.
523  */
524  peer_san = (STACK_OF(GENERAL_NAME) *)
525  X509_get_ext_d2i(conn->peer, NID_subject_alt_name, NULL, NULL);
526 
527  if (peer_san)
528  {
529  int san_len = sk_GENERAL_NAME_num(peer_san);
530 
531  for (i = 0; i < san_len; i++)
532  {
533  const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i);
534 
535  if (name->type == GEN_DNS)
536  {
537  char *alt_name;
538 
539  (*names_examined)++;
541  name->d.dNSName,
542  &alt_name);
543 
544  if (alt_name)
545  {
546  if (!*first_name)
547  *first_name = alt_name;
548  else
549  free(alt_name);
550  }
551  }
552  if (rc != 0)
553  break;
554  }
555  sk_GENERAL_NAME_free(peer_san);
556  }
557 
558  /*
559  * If there is no subjectAltName extension of type dNSName, check the
560  * Common Name.
561  *
562  * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
563  * dNSName is present, the CN must be ignored.)
564  */
565  if (*names_examined == 0)
566  {
567  X509_NAME *subject_name;
568 
569  subject_name = X509_get_subject_name(conn->peer);
570  if (subject_name != NULL)
571  {
572  int cn_index;
573 
574  cn_index = X509_NAME_get_index_by_NID(subject_name,
575  NID_commonName, -1);
576  if (cn_index >= 0)
577  {
578  (*names_examined)++;
580  X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, cn_index)),
581  first_name);
582  }
583  }
584  }
585 
586  return rc;
587 }
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 274 of file fe-secure-openssl.c.

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

Referenced by pqsecure_write().

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

◆ PQdefaultSSLKeyPassHook()

int PQdefaultSSLKeyPassHook ( char *  buf,
int  size,
PGconn conn 
)

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

Referenced by PQssl_passwd_cb().

1674 {
1675  if (conn->sslpassword)
1676  {
1677  if (strlen(conn->sslpassword) + 1 > size)
1678  fprintf(stderr, libpq_gettext("WARNING: sslpassword truncated"));
1679  strncpy(buf, conn->sslpassword, size);
1680  buf[size-1] = '\0';
1681  return strlen(buf);
1682  }
1683  else
1684  {
1685  buf[0] = '\0';
1686  return 0;
1687  }
1688 }
#define fprintf
Definition: port.h:197
static char * buf
Definition: pg_test_fsync.c:67
char * sslpassword
Definition: libpq-int.h:362
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ PQgetssl()

void* PQgetssl ( PGconn conn)

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

1451 {
1452  if (!conn)
1453  return NULL;
1454  return conn->ssl;
1455 }

◆ PQgetSSLKeyPassHook()

PQsslKeyPassHook_type PQgetSSLKeyPassHook ( void  )

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

1692 {
1693  return PQsslKeyPassHook;
1694 }
static PQsslKeyPassHook_type PQsslKeyPassHook

◆ PQsetSSLKeyPassHook()

void PQsetSSLKeyPassHook ( PQsslKeyPassHook_type  hook)

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

1698 {
1699  PQsslKeyPassHook = hook;
1700 }
static PQsslKeyPassHook_type PQsslKeyPassHook

◆ PQssl_passwd_cb()

static int PQssl_passwd_cb ( char *  buf,
int  size,
int  rwflag,
void *  userdata 
)
static

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

References PQdefaultSSLKeyPassHook(), and PQsslKeyPassHook.

Referenced by initialize_SSL().

1709 {
1710  PGconn *conn = userdata;
1711 
1712  if (PQsslKeyPassHook)
1713  return PQsslKeyPassHook(buf, size, conn);
1714  else
1715  return PQdefaultSSLKeyPassHook(buf, size, conn);
1716 }
int PQdefaultSSLKeyPassHook(char *buf, int size, PGconn *conn)
PGconn * conn
Definition: streamutil.c:54
static char * buf
Definition: pg_test_fsync.c:67
static PQsslKeyPassHook_type PQsslKeyPassHook

◆ PQsslAttribute()

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

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

Referenced by printSSLInfo().

1484 {
1485  if (!conn)
1486  return NULL;
1487  if (conn->ssl == NULL)
1488  return NULL;
1489 
1490  if (strcmp(attribute_name, "library") == 0)
1491  return "OpenSSL";
1492 
1493  if (strcmp(attribute_name, "key_bits") == 0)
1494  {
1495  static char sslbits_str[12];
1496  int sslbits;
1497 
1498  SSL_get_cipher_bits(conn->ssl, &sslbits);
1499  snprintf(sslbits_str, sizeof(sslbits_str), "%d", sslbits);
1500  return sslbits_str;
1501  }
1502 
1503  if (strcmp(attribute_name, "cipher") == 0)
1504  return SSL_get_cipher(conn->ssl);
1505 
1506  if (strcmp(attribute_name, "compression") == 0)
1507  return SSL_get_current_compression(conn->ssl) ? "on" : "off";
1508 
1509  if (strcmp(attribute_name, "protocol") == 0)
1510  return SSL_get_version(conn->ssl);
1511 
1512  return NULL; /* unknown attribute */
1513 }
#define snprintf
Definition: port.h:193

◆ PQsslAttributeNames()

const char* const* PQsslAttributeNames ( PGconn conn)

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

1469 {
1470  static const char *const result[] = {
1471  "library",
1472  "key_bits",
1473  "cipher",
1474  "compression",
1475  "protocol",
1476  NULL
1477  };
1478 
1479  return result;
1480 }

◆ PQsslStruct()

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

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

1459 {
1460  if (!conn)
1461  return NULL;
1462  if (strcmp(struct_name, "OpenSSL") == 0)
1463  return conn->ssl;
1464  return NULL;
1465 }

◆ ssl_protocol_version_to_openssl()

static int ssl_protocol_version_to_openssl ( const char *  protocol)
static

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

References pg_strcasecmp().

Referenced by initialize_SSL().

1730 {
1731  if (pg_strcasecmp("TLSv1", protocol) == 0)
1732  return TLS1_VERSION;
1733 
1734 #ifdef TLS1_1_VERSION
1735  if (pg_strcasecmp("TLSv1.1", protocol) == 0)
1736  return TLS1_1_VERSION;
1737 #endif
1738 
1739 #ifdef TLS1_2_VERSION
1740  if (pg_strcasecmp("TLSv1.2", protocol) == 0)
1741  return TLS1_2_VERSION;
1742 #endif
1743 
1744 #ifdef TLS1_3_VERSION
1745  if (pg_strcasecmp("TLSv1.3", protocol) == 0)
1746  return TLS1_3_VERSION;
1747 #endif
1748 
1749  return -1;
1750 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36

◆ SSLerrfree()

static void SSLerrfree ( char *  buf)
static

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

References free, and ssl_nomem.

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

1437 {
1438  if (buf != ssl_nomem)
1439  free(buf);
1440 }
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 1412 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().

1413 {
1414  const char *errreason;
1415  char *errbuf;
1416 
1417  errbuf = malloc(SSL_ERR_LEN);
1418  if (!errbuf)
1419  return ssl_nomem;
1420  if (ecode == 0)
1421  {
1422  snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("no SSL error reported"));
1423  return errbuf;
1424  }
1425  errreason = ERR_reason_error_string(ecode);
1426  if (errreason != NULL)
1427  {
1428  strlcpy(errbuf, errreason, SSL_ERR_LEN);
1429  return errbuf;
1430  }
1431  snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("SSL error code %lu"), ecode);
1432  return errbuf;
1433 }
#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 snprintf
Definition: port.h:193
#define SSL_ERR_LEN
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ verify_cb()

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

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

Referenced by initialize_SSL().

467 {
468  return ok;
469 }

Variable Documentation

◆ my_bio_methods

BIO_METHOD* my_bio_methods
static

Definition at line 1531 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 83 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 82 of file fe-secure-openssl.c.

Referenced by pgtls_init(), and pgtls_init_library().

◆ PQsslKeyPassHook

PQsslKeyPassHook_type PQsslKeyPassHook = NULL
static

◆ ssl_lib_initialized

bool ssl_lib_initialized = false
static

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

Referenced by SSLerrfree(), and SSLerrmessage().