PostgreSQL Source Code git master
Loading...
Searching...
No Matches
fe-secure-openssl.c File Reference
#include "postgres_fe.h"
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <limits.h>
#include "libpq-fe.h"
#include "fe-auth.h"
#include "fe-secure-common.h"
#include "libpq-int.h"
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <pthread.h>
#include "common/openssl.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
 

Functions

static int verify_cb (int ok, X509_STORE_CTX *ctx)
 
static int openssl_verify_peer_name_matches_certificate_name (PGconn *conn, const ASN1_STRING *name_entry, char **store_name)
 
static int openssl_verify_peer_name_matches_certificate_ip (PGconn *conn, ASN1_OCTET_STRING *addr_entry, char **store_name)
 
static int initialize_SSL (PGconn *conn)
 
static PostgresPollingStatusType open_client_SSL (PGconn *conn)
 
static charSSLerrmessage (unsigned long ecode)
 
static void SSLerrfree (char *buf)
 
static int PQssl_passwd_cb (char *buf, int size, int rwflag, void *userdata)
 
static int pgconn_bio_read (BIO *h, char *buf, int size)
 
static int pgconn_bio_write (BIO *h, const char *buf, int size)
 
static BIO_METHODpgconn_bio_method (void)
 
static int ssl_set_pgconn_bio (PGconn *conn)
 
static int ssl_protocol_version_to_openssl (const char *protocol)
 
PostgresPollingStatusType pgtls_open_client (PGconn *conn)
 
ssize_t pgtls_read (PGconn *conn, void *ptr, size_t len)
 
ssize_t pgtls_bytes_pending (PGconn *conn)
 
ssize_t pgtls_write (PGconn *conn, const void *ptr, size_t len)
 
charpgtls_get_peer_certificate_hash (PGconn *conn, size_t *len)
 
static bool is_ip_address (const char *host)
 
int pgtls_verify_peer_name_matches_certificate_guts (PGconn *conn, int *names_examined, char **first_name)
 
void pgtls_close (PGconn *conn)
 
voidPQgetssl (PGconn *conn)
 
voidPQsslStruct (PGconn *conn, const char *struct_name)
 
const char *constPQsslAttributeNames (PGconn *conn)
 
const charPQsslAttribute (PGconn *conn, const char *attribute_name)
 
static long pgconn_bio_ctrl (BIO *h, int cmd, long num, void *ptr)
 
int PQdefaultSSLKeyPassHook_OpenSSL (char *buf, int size, PGconn *conn)
 
PQsslKeyPassHook_OpenSSL_type PQgetSSLKeyPassHook_OpenSSL (void)
 
void PQsetSSLKeyPassHook_OpenSSL (PQsslKeyPassHook_OpenSSL_type hook)
 

Variables

static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER
 
static PQsslKeyPassHook_OpenSSL_type PQsslKeyPassHook = NULL
 
static unsigned char alpn_protos [] = PG_ALPN_PROTOCOL_VECTOR
 
static char ssl_nomem [] = "out of memory allocating error description"
 
static BIO_METHODpgconn_bio_method_ptr
 

Macro Definition Documentation

◆ SSL_ERR_LEN

#define SSL_ERR_LEN   128

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

Function Documentation

◆ initialize_SSL()

static int initialize_SSL ( PGconn conn)
static

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

772{
774 struct stat buf;
775 char homedir[MAXPGPATH];
776 char fnbuf[MAXPGPATH];
778 bool have_homedir;
779 bool have_cert;
780 bool have_rootcert;
781
782 /*
783 * We'll need the home directory if any of the relevant parameters are
784 * defaulted. If pqGetHomeDirectory fails, act as though none of the
785 * files could be found.
786 */
787 if (!(conn->sslcert && strlen(conn->sslcert) > 0) ||
788 !(conn->sslkey && strlen(conn->sslkey) > 0) ||
789 !(conn->sslrootcert && strlen(conn->sslrootcert) > 0) ||
790 !((conn->sslcrl && strlen(conn->sslcrl) > 0) ||
791 (conn->sslcrldir && strlen(conn->sslcrldir) > 0)))
793 else /* won't need it */
794 have_homedir = false;
795
796 /*
797 * Create a new SSL_CTX object.
798 *
799 * We used to share a single SSL_CTX between all connections, but it was
800 * complicated if connections used different certificates. So now we
801 * create a separate context for each connection, and accept the overhead.
802 */
804 if (!SSL_context)
805 {
807
808 libpq_append_conn_error(conn, "could not create SSL context: %s", err);
810 return -1;
811 }
812
813 /*
814 * Delegate the client cert password prompt to the libpq wrapper callback
815 * if any is defined.
816 *
817 * If the application hasn't installed its own and the sslpassword
818 * parameter is non-null, we install ours now to make sure we supply
819 * PGconn->sslpassword to OpenSSL instead of letting it prompt on stdin.
820 *
821 * This will replace OpenSSL's default PEM_def_callback (which prompts on
822 * stdin), but we're only setting it for this SSL context so it's
823 * harmless.
824 */
826 || (conn->sslpassword && strlen(conn->sslpassword) > 0))
827 {
830 }
831
832#ifdef HAVE_SSL_CTX_SET_CERT_CB
833 /* Set up a certificate selection callback. */
835#endif
836
837 /* Disable old protocol versions */
839
840 /* Set the minimum and maximum protocol versions if necessary */
843 {
844 int ssl_min_ver;
845
847
848 if (ssl_min_ver == -1)
849 {
850 libpq_append_conn_error(conn, "invalid value \"%s\" for minimum SSL protocol version",
853 return -1;
854 }
855
857 {
859
860 libpq_append_conn_error(conn, "could not set minimum SSL protocol version: %s", err);
863 return -1;
864 }
865 }
866
869 {
870 int ssl_max_ver;
871
873
874 if (ssl_max_ver == -1)
875 {
876 libpq_append_conn_error(conn, "invalid value \"%s\" for maximum SSL protocol version",
879 return -1;
880 }
881
883 {
885
886 libpq_append_conn_error(conn, "could not set maximum SSL protocol version: %s", err);
889 return -1;
890 }
891 }
892
893 /*
894 * Disable OpenSSL's moving-write-buffer sanity check, because it causes
895 * unnecessary failures in nonblocking send cases.
896 */
898
899 /*
900 * If the root cert file exists, load it so we can perform certificate
901 * verification. If sslmode is "verify-full" we will also do further
902 * verification after the connection has been completed.
903 */
904 if (conn->sslrootcert && strlen(conn->sslrootcert) > 0)
905 strlcpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
906 else if (have_homedir)
907 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
908 else
909 fnbuf[0] = '\0';
910
911 if (strcmp(fnbuf, "system") == 0)
912 {
913 /*
914 * The "system" sentinel value indicates that we should load whatever
915 * root certificates are installed for use by OpenSSL; these locations
916 * differ by platform. Note that the default system locations may be
917 * further overridden by the SSL_CERT_DIR and SSL_CERT_FILE
918 * environment variables.
919 */
921 {
923
924 libpq_append_conn_error(conn, "could not load system root certificate paths: %s",
925 err);
928 return -1;
929 }
930 have_rootcert = true;
931 }
932 else if (fnbuf[0] != '\0' &&
933 stat(fnbuf, &buf) == 0)
934 {
936
938 {
940
941 libpq_append_conn_error(conn, "could not read root certificate file \"%s\": %s",
942 fnbuf, err);
945 return -1;
946 }
947
949 {
950 char *fname = NULL;
951 char *dname = NULL;
952
953 if (conn->sslcrl && strlen(conn->sslcrl) > 0)
954 fname = conn->sslcrl;
955 if (conn->sslcrldir && strlen(conn->sslcrldir) > 0)
957
958 /* defaults to use the default CRL file */
959 if (!fname && !dname && have_homedir)
960 {
961 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE);
962 fname = fnbuf;
963 }
964
965 /* Set the flags to check against the complete CRL chain */
966 if ((fname || dname) &&
968 {
971 }
972
973 /* if not found, silently ignore; we do not require CRL */
975 }
976 have_rootcert = true;
977 }
978 else
979 {
980 /*
981 * stat() failed; assume root file doesn't exist. If sslmode is
982 * verify-ca or verify-full, this is an error. Otherwise, continue
983 * without performing any server cert verification.
984 */
985 if (conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */
986 {
987 /*
988 * The only way to reach here with an empty filename is if
989 * pqGetHomeDirectory failed. That's a sufficiently unusual case
990 * that it seems worth having a specialized error message for it.
991 */
992 if (fnbuf[0] == '\0')
993 libpq_append_conn_error(conn, "could not get home directory to locate root certificate file\n"
994 "Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification.");
995 else
996 libpq_append_conn_error(conn, "root certificate file \"%s\" does not exist\n"
997 "Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification.", fnbuf);
999 return -1;
1000 }
1001 have_rootcert = false;
1002 }
1003
1004 /* Read the client certificate file */
1005 if (conn->sslcert && strlen(conn->sslcert) > 0)
1006 strlcpy(fnbuf, conn->sslcert, sizeof(fnbuf));
1007 else if (have_homedir)
1008 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
1009 else
1010 fnbuf[0] = '\0';
1011
1012 if (conn->sslcertmode[0] == 'd') /* disable */
1013 {
1014 /* don't send a client cert even if we have one */
1015 have_cert = false;
1016 }
1017 else if (fnbuf[0] == '\0')
1018 {
1019 /* no home directory, proceed without a client cert */
1020 have_cert = false;
1021 }
1022 else if (stat(fnbuf, &buf) != 0)
1023 {
1024 /*
1025 * If file is not present, just go on without a client cert; server
1026 * might or might not accept the connection. Any other error,
1027 * however, is grounds for complaint.
1028 */
1029 if (errno != ENOENT && errno != ENOTDIR)
1030 {
1031 libpq_append_conn_error(conn, "could not open certificate file \"%s\": %s",
1032 fnbuf, strerror_r(errno, sebuf, sizeof(sebuf)));
1034 return -1;
1035 }
1036 have_cert = false;
1037 }
1038 else
1039 {
1040 /*
1041 * Cert file exists, so load it. Since OpenSSL doesn't provide the
1042 * equivalent of "SSL_use_certificate_chain_file", we have to load it
1043 * into the SSL context, rather than the SSL object.
1044 */
1046 {
1047 char *err = SSLerrmessage(ERR_get_error());
1048
1049 libpq_append_conn_error(conn, "could not read certificate file \"%s\": %s",
1050 fnbuf, err);
1051 SSLerrfree(err);
1053 return -1;
1054 }
1055
1056 /* need to load the associated private key, too */
1057 have_cert = true;
1058 }
1059
1060 /*
1061 * The SSL context is now loaded with the correct root and client
1062 * certificates. Create a connection-specific SSL object. The private key
1063 * is loaded directly into the SSL object. (We could load the private key
1064 * into the context, too, but we have done it this way historically, and
1065 * it doesn't really matter.)
1066 */
1067 if (!(conn->ssl = SSL_new(SSL_context)) ||
1068 !SSL_set_app_data(conn->ssl, conn) ||
1070 {
1071 char *err = SSLerrmessage(ERR_get_error());
1072
1073 libpq_append_conn_error(conn, "could not establish SSL connection: %s", err);
1074 SSLerrfree(err);
1076 return -1;
1077 }
1078 conn->ssl_in_use = true;
1079
1080 /*
1081 * If SSL key logging is requested, set up the callback if a compatible
1082 * version of OpenSSL is used and libpq was compiled to support it.
1083 */
1085 {
1086#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK
1088#else
1089#ifdef LIBRESSL_VERSION_NUMBER
1090 fprintf(stderr, libpq_gettext("WARNING: sslkeylogfile support requires OpenSSL\n"));
1091#else
1092 fprintf(stderr, libpq_gettext("WARNING: libpq was not built with sslkeylogfile support\n"));
1093#endif
1094#endif
1095 }
1096
1097 /*
1098 * SSL contexts are reference counted by OpenSSL. We can free it as soon
1099 * as we have created the SSL object, and it will stick around for as long
1100 * as it's actually needed.
1101 */
1103 SSL_context = NULL;
1104
1105 /*
1106 * Set Server Name Indication (SNI), if enabled by connection parameters.
1107 * Per RFC 6066, do not set it if the host is a literal IP address (IPv4
1108 * or IPv6).
1109 */
1110 if (conn->sslsni && conn->sslsni[0] == '1')
1111 {
1112 const char *host = conn->connhost[conn->whichhost].host;
1113
1114 if (host && host[0] &&
1115 !(strspn(host, "0123456789.") == strlen(host) ||
1116 strchr(host, ':')))
1117 {
1118 if (SSL_set_tlsext_host_name(conn->ssl, host) != 1)
1119 {
1120 char *err = SSLerrmessage(ERR_get_error());
1121
1122 libpq_append_conn_error(conn, "could not set SSL Server Name Indication (SNI): %s", err);
1123 SSLerrfree(err);
1124 return -1;
1125 }
1126 }
1127 }
1128
1129 /* Set ALPN */
1130 {
1131 int retval;
1132
1133 retval = SSL_set_alpn_protos(conn->ssl, alpn_protos, sizeof(alpn_protos));
1134
1135 if (retval != 0)
1136 {
1137 char *err = SSLerrmessage(ERR_get_error());
1138
1139 libpq_append_conn_error(conn, "could not set SSL ALPN extension: %s", err);
1140 SSLerrfree(err);
1141 return -1;
1142 }
1143 }
1144
1145 /*
1146 * Read the SSL key. If a key is specified, treat it as an engine:key
1147 * combination if there is colon present - we don't support files with
1148 * colon in the name. The exception is if the second character is a colon,
1149 * in which case it can be a Windows filename with drive specification.
1150 */
1151 if (have_cert && conn->sslkey && strlen(conn->sslkey) > 0)
1152 {
1153#ifdef USE_SSL_ENGINE
1154 if (strchr(conn->sslkey, ':')
1155#ifdef WIN32
1156 && conn->sslkey[1] != ':'
1157#endif
1158 )
1159 {
1160 /* Colon, but not in second character, treat as engine:key */
1161 char *engine_str = strdup(conn->sslkey);
1162 char *engine_colon;
1163 EVP_PKEY *pkey;
1164
1165 if (engine_str == NULL)
1166 {
1167 libpq_append_conn_error(conn, "out of memory");
1168 return -1;
1169 }
1170
1171 /* cannot return NULL because we already checked before strdup */
1173
1174 *engine_colon = '\0'; /* engine_str now has engine name */
1175 engine_colon++; /* engine_colon now has key name */
1176
1177 conn->engine = ENGINE_by_id(engine_str);
1178 if (conn->engine == NULL)
1179 {
1180 char *err = SSLerrmessage(ERR_get_error());
1181
1182 libpq_append_conn_error(conn, "could not load SSL engine \"%s\": %s",
1183 engine_str, err);
1184 SSLerrfree(err);
1186 return -1;
1187 }
1188
1189 if (ENGINE_init(conn->engine) == 0)
1190 {
1191 char *err = SSLerrmessage(ERR_get_error());
1192
1193 libpq_append_conn_error(conn, "could not initialize SSL engine \"%s\": %s",
1194 engine_str, err);
1195 SSLerrfree(err);
1196 ENGINE_free(conn->engine);
1197 conn->engine = NULL;
1199 return -1;
1200 }
1201
1203 NULL, NULL);
1204 if (pkey == NULL)
1205 {
1206 char *err = SSLerrmessage(ERR_get_error());
1207
1208 libpq_append_conn_error(conn, "could not read private SSL key \"%s\" from engine \"%s\": %s",
1210 SSLerrfree(err);
1211 ENGINE_finish(conn->engine);
1212 ENGINE_free(conn->engine);
1213 conn->engine = NULL;
1215 return -1;
1216 }
1217 if (SSL_use_PrivateKey(conn->ssl, pkey) != 1)
1218 {
1219 char *err = SSLerrmessage(ERR_get_error());
1220
1221 libpq_append_conn_error(conn, "could not load private SSL key \"%s\" from engine \"%s\": %s",
1223 SSLerrfree(err);
1224 ENGINE_finish(conn->engine);
1225 ENGINE_free(conn->engine);
1226 conn->engine = NULL;
1228 return -1;
1229 }
1230
1232
1233 fnbuf[0] = '\0'; /* indicate we're not going to load from a
1234 * file */
1235 }
1236 else
1237#endif /* USE_SSL_ENGINE */
1238 {
1239 /* PGSSLKEY is not an engine, treat it as a filename */
1240 strlcpy(fnbuf, conn->sslkey, sizeof(fnbuf));
1241 }
1242 }
1243 else if (have_homedir)
1244 {
1245 /* No PGSSLKEY specified, load default file */
1246 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
1247 }
1248 else
1249 fnbuf[0] = '\0';
1250
1251 if (have_cert && fnbuf[0] != '\0')
1252 {
1253 /* read the client key from file */
1254
1255 if (stat(fnbuf, &buf) != 0)
1256 {
1257 if (errno == ENOENT)
1258 libpq_append_conn_error(conn, "certificate present, but not private key file \"%s\"",
1259 fnbuf);
1260 else
1261 libpq_append_conn_error(conn, "could not stat private key file \"%s\": %m",
1262 fnbuf);
1263 return -1;
1264 }
1265
1266 /* Key file must be a regular file */
1267 if (!S_ISREG(buf.st_mode))
1268 {
1269 libpq_append_conn_error(conn, "private key file \"%s\" is not a regular file",
1270 fnbuf);
1271 return -1;
1272 }
1273
1274 /*
1275 * Refuse to load world-readable key files. We accept root-owned
1276 * files with mode 0640 or less, so that we can access system-wide
1277 * certificates if we have a supplementary group membership that
1278 * allows us to read 'em. For files with non-root ownership, require
1279 * mode 0600 or less. We need not check the file's ownership exactly;
1280 * if we're able to read it despite it having such restrictive
1281 * permissions, it must have the right ownership.
1282 *
1283 * Note: be very careful about tightening these rules. Some people
1284 * expect, for example, that a client process running as root should
1285 * be able to use a non-root-owned key file.
1286 *
1287 * Note that roughly similar checks are performed in
1288 * src/backend/libpq/be-secure-common.c so any changes here may need
1289 * to be made there as well. However, this code caters for the case
1290 * of current user == root, while that code does not.
1291 *
1292 * Ideally we would do similar permissions checks on Windows, but it
1293 * is not clear how that would work since Unix-style permissions may
1294 * not be available.
1295 */
1296#if !defined(WIN32) && !defined(__CYGWIN__)
1297 if (buf.st_uid == 0 ?
1298 buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO) :
1299 buf.st_mode & (S_IRWXG | S_IRWXO))
1300 {
1302 "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root",
1303 fnbuf);
1304 return -1;
1305 }
1306#endif
1307
1309 {
1310 char *err = SSLerrmessage(ERR_get_error());
1311
1312 /*
1313 * We'll try to load the file in DER (binary ASN.1) format, and if
1314 * that fails too, report the original error. This could mask
1315 * issues where there's something wrong with a DER-format cert,
1316 * but we'd have to duplicate openssl's format detection to be
1317 * smarter than this. We can't just probe for a leading -----BEGIN
1318 * because PEM can have leading non-matching lines and blanks.
1319 * OpenSSL doesn't expose its get_name(...) and its PEM routines
1320 * don't differentiate between failure modes in enough detail to
1321 * let us tell the difference between "not PEM, try DER" and
1322 * "wrong password".
1323 */
1325 {
1326 libpq_append_conn_error(conn, "could not load private key file \"%s\": %s",
1327 fnbuf, err);
1328 SSLerrfree(err);
1329 return -1;
1330 }
1331
1332 SSLerrfree(err);
1333 }
1334 }
1335
1336 /* verify that the cert and key go together */
1337 if (have_cert &&
1338 SSL_check_private_key(conn->ssl) != 1)
1339 {
1340 char *err = SSLerrmessage(ERR_get_error());
1341
1342 libpq_append_conn_error(conn, "certificate does not match private key file \"%s\": %s",
1343 fnbuf, err);
1344 SSLerrfree(err);
1345 return -1;
1346 }
1347
1348 /*
1349 * If a root cert was loaded, also set our certificate verification
1350 * callback.
1351 */
1352 if (have_rootcert)
1354
1355 /*
1356 * Set compression option if necessary.
1357 */
1358 if (conn->sslcompression && conn->sslcompression[0] == '0')
1360 else
1362
1363 return 0;
1364}
static SSL_CTX * SSL_context
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
void err(int eval, const char *fmt,...)
Definition err.c:43
bool pqGetHomeDirectory(char *buf, int bufsize)
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition fe-misc.c:1548
static int ssl_protocol_version_to_openssl(const char *protocol)
static void SSLerrfree(char *buf)
static PQsslKeyPassHook_OpenSSL_type PQsslKeyPassHook
static int verify_cb(int ok, X509_STORE_CTX *ctx)
static int PQssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
static char * SSLerrmessage(unsigned long ecode)
static unsigned char alpn_protos[]
static int ssl_set_pgconn_bio(PGconn *conn)
#define libpq_gettext(x)
Definition oauth-utils.h:44
#define MAXPGPATH
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define PG_STRERROR_R_BUFLEN
Definition port.h:279
#define snprintf
Definition port.h:261
#define strerror_r
Definition port.h:278
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
static int fb(int x)
#define free(a)
PGconn * conn
Definition streamutil.c:52
char * host
Definition libpq-int.h:360
char * sslrootcert
Definition libpq-int.h:415
char * sslcompression
Definition libpq-int.h:410
char * sslcrldir
Definition libpq-int.h:417
char * sslcrl
Definition libpq-int.h:416
char * ssl_max_protocol_version
Definition libpq-int.h:428
char * sslcert
Definition libpq-int.h:412
char * sslcertmode
Definition libpq-int.h:414
char * sslpassword
Definition libpq-int.h:413
char * sslmode
Definition libpq-int.h:408
char * ssl_min_protocol_version
Definition libpq-int.h:427
char * sslkey
Definition libpq-int.h:411
char * sslkeylogfile
Definition libpq-int.h:434
int whichhost
Definition libpq-int.h:484
char * sslsni
Definition libpq-int.h:418
pg_conn_host * connhost
Definition libpq-int.h:485
bool ssl_in_use
Definition libpq-int.h:623
#define S_IXGRP
Definition win32_port.h:314
#define stat
Definition win32_port.h:74
#define S_IRWXG
Definition win32_port.h:317
#define S_IRWXO
Definition win32_port.h:329
#define S_ISREG(m)
Definition win32_port.h:335
#define S_IWGRP
Definition win32_port.h:311

References alpn_protos, buf, conn, pg_conn::connhost, err(), fb(), fprintf, free, pg_conn_host::host, libpq_append_conn_error(), libpq_gettext, MAXPGPATH, PG_STRERROR_R_BUFLEN, pqGetHomeDirectory(), PQssl_passwd_cb(), PQsslKeyPassHook, S_IRWXG, S_IRWXO, S_ISREG, S_IWGRP, S_IXGRP, snprintf, SSL_context, pg_conn::ssl_in_use, pg_conn::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, ssl_protocol_version_to_openssl(), ssl_set_pgconn_bio(), pg_conn::sslcert, pg_conn::sslcertmode, pg_conn::sslcompression, pg_conn::sslcrl, pg_conn::sslcrldir, SSLerrfree(), SSLerrmessage(), pg_conn::sslkey, pg_conn::sslkeylogfile, pg_conn::sslmode, pg_conn::sslpassword, pg_conn::sslrootcert, pg_conn::sslsni, stat, strerror_r, strlcpy(), verify_cb(), and pg_conn::whichhost.

Referenced by pgtls_open_client().

◆ is_ip_address()

static bool is_ip_address ( const char host)
static

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

557{
558 struct in_addr dummy4;
559#ifdef HAVE_INET_PTON
560 struct in6_addr dummy6;
561#endif
562
563 return inet_aton(host, &dummy4)
564#ifdef HAVE_INET_PTON
565 || (inet_pton(AF_INET6, host, &dummy6) == 1)
566#endif
567 ;
568}
int inet_aton(const char *cp, struct in_addr *addr)
Definition inet_aton.c:58

References fb(), and inet_aton().

Referenced by pgtls_verify_peer_name_matches_certificate_guts().

◆ open_client_SSL()

static PostgresPollingStatusType open_client_SSL ( PGconn conn)
static

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

1371{
1372 int r;
1373
1374 SOCK_ERRNO_SET(0);
1376 r = SSL_connect(conn->ssl);
1377 if (r <= 0)
1378 {
1379 int save_errno = SOCK_ERRNO;
1380 int err = SSL_get_error(conn->ssl, r);
1381 unsigned long ecode;
1382
1383 ecode = ERR_get_error();
1384 switch (err)
1385 {
1387 return PGRES_POLLING_READING;
1388
1390 return PGRES_POLLING_WRITING;
1391
1392 case SSL_ERROR_SYSCALL:
1393 {
1395 unsigned long vcode;
1396
1398
1399 /*
1400 * If we get an X509 error here for failing to load the
1401 * local issuer cert, without an error in the socket layer
1402 * it means that verification failed due to a missing
1403 * system CA pool without it being a protocol error. We
1404 * inspect the sslrootcert setting to ensure that the user
1405 * was using the system CA pool. For other errors, log
1406 * them using the normal SYSCALL logging.
1407 */
1408 if (save_errno == 0 &&
1410 strcmp(conn->sslrootcert, "system") == 0)
1411 libpq_append_conn_error(conn, "SSL error: certificate verify failed: %s",
1413 else if (r == -1 && save_errno != 0)
1414 libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
1415 SOCK_STRERROR(save_errno, sebuf, sizeof(sebuf)));
1416 else
1417 libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
1419 return PGRES_POLLING_FAILED;
1420 }
1421 case SSL_ERROR_SSL:
1422 {
1423 char *err = SSLerrmessage(ecode);
1424
1425 libpq_append_conn_error(conn, "SSL error: %s", err);
1426 SSLerrfree(err);
1427 switch (ERR_GET_REASON(ecode))
1428 {
1429 /*
1430 * UNSUPPORTED_PROTOCOL, WRONG_VERSION_NUMBER, and
1431 * TLSV1_ALERT_PROTOCOL_VERSION have been observed
1432 * when trying to communicate with an old OpenSSL
1433 * library, or when the client and server specify
1434 * disjoint protocol ranges.
1435 * NO_PROTOCOLS_AVAILABLE occurs if there's a
1436 * local misconfiguration (which can happen
1437 * despite our checks, if openssl.cnf injects a
1438 * limit we didn't account for). It's not very
1439 * clear what would make OpenSSL return the other
1440 * codes listed here, but a hint about protocol
1441 * versions seems like it's appropriate for all.
1442 */
1452#ifdef SSL_R_VERSION_TOO_HIGH
1455#endif
1456 libpq_append_conn_error(conn, "This may indicate that the server does not support any SSL protocol version between %s and %s.",
1463 break;
1464 default:
1465 break;
1466 }
1468 return PGRES_POLLING_FAILED;
1469 }
1470
1471 default:
1472 libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
1474 return PGRES_POLLING_FAILED;
1475 }
1476 }
1477
1478 /* ALPN is mandatory with direct SSL connections */
1479 if (conn->current_enc_method == ENC_SSL && conn->sslnegotiation[0] == 'd')
1480 {
1481 const unsigned char *selected;
1482 unsigned int len;
1483
1484 SSL_get0_alpn_selected(conn->ssl, &selected, &len);
1485
1486 if (selected == NULL)
1487 {
1488 libpq_append_conn_error(conn, "direct SSL connection was established without ALPN protocol negotiation extension");
1490 return PGRES_POLLING_FAILED;
1491 }
1492
1493 /*
1494 * We only support one protocol so that's what the negotiation should
1495 * always choose, but doesn't hurt to check.
1496 */
1497 if (len != strlen(PG_ALPN_PROTOCOL) ||
1499 {
1500 libpq_append_conn_error(conn, "SSL connection was established with unexpected ALPN protocol");
1502 return PGRES_POLLING_FAILED;
1503 }
1504 }
1505
1506 /*
1507 * We already checked the server certificate in initialize_SSL() using
1508 * SSL_CTX_set_verify(), if root.crt exists.
1509 */
1510
1511 /* get server certificate */
1512 conn->peer = SSL_get_peer_certificate(conn->ssl);
1513 if (conn->peer == NULL)
1514 {
1515 char *err = SSLerrmessage(ERR_get_error());
1516
1517 libpq_append_conn_error(conn, "certificate could not be obtained: %s", err);
1518 SSLerrfree(err);
1520 return PGRES_POLLING_FAILED;
1521 }
1522
1524 {
1526 return PGRES_POLLING_FAILED;
1527 }
1528
1529 /* SSL handshake is complete */
1530 return PGRES_POLLING_OK;
1531}
int ssl_max_protocol_version
Definition be-secure.c:62
bool pq_verify_peer_name_matches_certificate(PGconn *conn)
void pgtls_close(PGconn *conn)
@ PGRES_POLLING_OK
Definition libpq-fe.h:124
@ PGRES_POLLING_READING
Definition libpq-fe.h:122
@ PGRES_POLLING_WRITING
Definition libpq-fe.h:123
@ PGRES_POLLING_FAILED
Definition libpq-fe.h:121
#define SOCK_STRERROR
Definition libpq-int.h:983
#define ENC_SSL
Definition libpq-int.h:233
#define SOCK_ERRNO
Definition oauth-utils.c:86
#define SOCK_ERRNO_SET(e)
Definition oauth-utils.c:87
const void size_t len
#define PG_ALPN_PROTOCOL
Definition pqcomm.h:189
char * sslnegotiation
Definition libpq-int.h:409
uint8 current_enc_method
Definition libpq-int.h:620

References conn, pg_conn::current_enc_method, ENC_SSL, err(), fb(), len, libpq_append_conn_error(), PG_ALPN_PROTOCOL, PG_STRERROR_R_BUFLEN, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, pgtls_close(), pq_verify_peer_name_matches_certificate(), SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, pg_conn::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, SSLerrfree(), SSLerrmessage(), pg_conn::sslnegotiation, and pg_conn::sslrootcert.

Referenced by pgtls_open_client().

◆ openssl_verify_peer_name_matches_certificate_ip()

static int openssl_verify_peer_name_matches_certificate_ip ( PGconn conn,
ASN1_OCTET_STRING addr_entry,
char **  store_name 
)
static

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

534{
535 int len;
536 const unsigned char *addrdata;
537
538 /* Should not happen... */
539 if (addr_entry == NULL)
540 {
541 libpq_append_conn_error(conn, "SSL certificate's address entry is missing");
542 return -1;
543 }
544
545 /*
546 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
547 * order.
548 */
551
553}
int pq_verify_peer_name_matches_certificate_ip(PGconn *conn, const unsigned char *ipdata, size_t iplen, char **store_name)

References conn, fb(), len, libpq_append_conn_error(), and pq_verify_peer_name_matches_certificate_ip().

Referenced by pgtls_verify_peer_name_matches_certificate_guts().

◆ openssl_verify_peer_name_matches_certificate_name()

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

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

504{
505 int len;
506 const unsigned char *namedata;
507
508 /* Should not happen... */
509 if (name_entry == NULL)
510 {
511 libpq_append_conn_error(conn, "SSL certificate's name entry is missing");
512 return -1;
513 }
514
515 /*
516 * GEN_DNS can be only IA5String, equivalent to US ASCII.
517 */
520
521 /* OK to cast from unsigned to plain char, since it's all ASCII. */
523}
int pq_verify_peer_name_matches_certificate_name(PGconn *conn, const char *namedata, size_t namelen, char **store_name)

References conn, fb(), len, libpq_append_conn_error(), and pq_verify_peer_name_matches_certificate_name().

Referenced by pgtls_verify_peer_name_matches_certificate_guts().

◆ pgconn_bio_ctrl()

static long pgconn_bio_ctrl ( BIO h,
int  cmd,
long  num,
void ptr 
)
static

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

1836{
1837 long res;
1838 PGconn *conn = (PGconn *) BIO_get_data(h);
1839
1840 switch (cmd)
1841 {
1842 case BIO_CTRL_EOF:
1843
1844 /*
1845 * This should not be needed. pgconn_bio_read already has a way to
1846 * signal EOF to OpenSSL. However, OpenSSL made an undocumented,
1847 * backwards-incompatible change and now expects EOF via BIO_ctrl.
1848 * See https://github.com/openssl/openssl/issues/8208
1849 */
1850 res = conn->last_read_was_eof;
1851 break;
1852 case BIO_CTRL_FLUSH:
1853 /* libssl expects all BIOs to support BIO_flush. */
1854 res = 1;
1855 break;
1856 default:
1857 res = 0;
1858 break;
1859 }
1860
1861 return res;
1862}
bool last_read_was_eof
Definition libpq-int.h:627

References conn, fb(), and pg_conn::last_read_was_eof.

Referenced by pgconn_bio_method().

◆ pgconn_bio_method()

static BIO_METHOD * pgconn_bio_method ( void  )
static

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

1866{
1867 BIO_METHOD *res;
1868
1870 return NULL;
1871
1873
1875 {
1876 int my_bio_index;
1877
1879 if (my_bio_index == -1)
1880 goto err;
1882 res = BIO_meth_new(my_bio_index, "libpq socket");
1883 if (!res)
1884 goto err;
1885
1886 /*
1887 * As of this writing, these functions never fail. But check anyway,
1888 * like OpenSSL's own examples do.
1889 */
1893 {
1894 goto err;
1895 }
1896 }
1897
1900 return res;
1901
1902err:
1903 if (res)
1904 BIO_meth_free(res);
1906 return NULL;
1907}
static BIO_METHOD * pgconn_bio_method_ptr
static int pgconn_bio_read(BIO *h, char *buf, int size)
static long pgconn_bio_ctrl(BIO *h, int cmd, long num, void *ptr)
static int pgconn_bio_write(BIO *h, const char *buf, int size)
static pthread_mutex_t ssl_config_mutex
int pthread_mutex_unlock(pthread_mutex_t *mp)
int pthread_mutex_lock(pthread_mutex_t *mp)

References err(), fb(), pgconn_bio_ctrl(), pgconn_bio_method_ptr, pgconn_bio_read(), pgconn_bio_write(), pthread_mutex_lock(), pthread_mutex_unlock(), and ssl_config_mutex.

Referenced by ssl_set_pgconn_bio().

◆ pgconn_bio_read()

static int pgconn_bio_read ( BIO h,
char buf,
int  size 
)
static

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

1771{
1772 PGconn *conn = (PGconn *) BIO_get_data(h);
1773 int res;
1774
1775 res = pqsecure_raw_read(conn, buf, size);
1777 conn->last_read_was_eof = res == 0;
1778 if (res < 0)
1779 {
1780 /* If we were interrupted, tell caller to retry */
1781 switch (SOCK_ERRNO)
1782 {
1783#ifdef EAGAIN
1784 case EAGAIN:
1785#endif
1786#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
1787 case EWOULDBLOCK:
1788#endif
1789 case EINTR:
1791 break;
1792
1793 default:
1794 break;
1795 }
1796 }
1797
1798 if (res > 0)
1800
1801 return res;
1802}
ssize_t pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
Definition fe-secure.c:193
bool ssl_handshake_started
Definition libpq-int.h:624
#define EINTR
Definition win32_port.h:378
#define EWOULDBLOCK
Definition win32_port.h:384
#define EAGAIN
Definition win32_port.h:376

References buf, conn, EAGAIN, EINTR, EWOULDBLOCK, fb(), pg_conn::last_read_was_eof, pqsecure_raw_read(), SOCK_ERRNO, and pg_conn::ssl_handshake_started.

Referenced by pgconn_bio_method().

◆ pgconn_bio_write()

static int pgconn_bio_write ( BIO h,
const char buf,
int  size 
)
static

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

1806{
1807 int res;
1808
1809 res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
1811 if (res < 0)
1812 {
1813 /* If we were interrupted, tell caller to retry */
1814 switch (SOCK_ERRNO)
1815 {
1816#ifdef EAGAIN
1817 case EAGAIN:
1818#endif
1819#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
1820 case EWOULDBLOCK:
1821#endif
1822 case EINTR:
1824 break;
1825
1826 default:
1827 break;
1828 }
1829 }
1830
1831 return res;
1832}
ssize_t pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
Definition fe-secure.c:340

References buf, EAGAIN, EINTR, EWOULDBLOCK, fb(), pqsecure_raw_write(), and SOCK_ERRNO.

Referenced by pgconn_bio_method().

◆ pgtls_bytes_pending()

ssize_t pgtls_bytes_pending ( PGconn conn)

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

236{
237 int pending;
238
239 /*
240 * OpenSSL readahead is documented to break SSL_pending(). Plus, we can't
241 * afford to have OpenSSL take bytes off the socket without processing
242 * them; that breaks the postconditions for pqsecure_drain_pending().
243 */
245
246 pending = SSL_pending(conn->ssl);
247 if (pending < 0)
248 {
249 /* shouldn't be possible */
250 Assert(false);
251 libpq_append_conn_error(conn, "OpenSSL reports negative bytes pending");
252 return -1;
253 }
254 else if (pending == INT_MAX)
255 {
256 /*
257 * If we ever found a legitimate way to hit this, we'd need to loop
258 * around in the caller to call pgtls_bytes_pending() again. Throw an
259 * error rather than complicate the code in that way, because
260 * SSL_read() should be bounded to the size of a single TLS record,
261 * and conn->inBuffer can't currently go past INT_MAX in size anyway.
262 */
263 libpq_append_conn_error(conn, "OpenSSL reports INT_MAX bytes pending");
264 return -1;
265 }
266
267 return (ssize_t) pending;
268}
#define Assert(condition)
Definition c.h:1002

References Assert, conn, fb(), and libpq_append_conn_error().

Referenced by pqsecure_bytes_pending().

◆ pgtls_close()

void pgtls_close ( PGconn conn)

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

1535{
1536 if (conn->ssl_in_use)
1537 {
1538 if (conn->ssl)
1539 {
1540 /*
1541 * We can't destroy everything SSL-related here due to the
1542 * possible later calls to OpenSSL routines which may need our
1543 * thread callbacks, so set a flag here and check at the end.
1544 */
1545
1546 SSL_shutdown(conn->ssl);
1547 SSL_free(conn->ssl);
1548 conn->ssl = NULL;
1549 conn->ssl_in_use = false;
1550 conn->ssl_handshake_started = false;
1551 }
1552
1553 if (conn->peer)
1554 {
1555 X509_free(conn->peer);
1556 conn->peer = NULL;
1557 }
1558
1559#ifdef USE_SSL_ENGINE
1560 if (conn->engine)
1561 {
1562 ENGINE_finish(conn->engine);
1563 ENGINE_free(conn->engine);
1564 conn->engine = NULL;
1565 }
1566#endif
1567 }
1568}

References conn, fb(), pg_conn::ssl_handshake_started, and pg_conn::ssl_in_use.

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

◆ pgtls_get_peer_certificate_hash()

char * pgtls_get_peer_certificate_hash ( PGconn conn,
size_t len 
)

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

372{
374 const EVP_MD *algo_type;
375 unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
376 unsigned int hash_size;
377 int algo_nid;
378 char *cert_hash;
379
380 *len = 0;
381
382 if (!conn->peer)
383 return NULL;
384
385 peer_cert = conn->peer;
386
387 /*
388 * Get the signature algorithm of the certificate to determine the hash
389 * algorithm to use for the result. Prefer X509_get_signature_info(),
390 * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
391 */
392#if HAVE_X509_GET_SIGNATURE_INFO
394#else
396 &algo_nid, NULL))
397#endif
398 {
399 libpq_append_conn_error(conn, "could not determine server certificate signature algorithm");
400 return NULL;
401 }
402
403 /*
404 * The TLS server's certificate bytes need to be hashed with SHA-256 if
405 * its signature algorithm is MD5 or SHA-1 as per RFC 5929
406 * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
407 * is used, the same hash as the signature algorithm is used.
408 */
409 switch (algo_nid)
410 {
411 case NID_md5:
412 case NID_sha1:
414 break;
415 default:
417 if (algo_type == NULL)
418 {
419 libpq_append_conn_error(conn, "could not find digest for NID %s",
421 return NULL;
422 }
423 break;
424 }
425
427 {
428 libpq_append_conn_error(conn, "could not generate peer certificate hash");
429 return NULL;
430 }
431
432 /* save result */
434 if (cert_hash == NULL)
435 {
436 libpq_append_conn_error(conn, "out of memory");
437 return NULL;
438 }
440 *len = hash_size;
441
442 return cert_hash;
443}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
static unsigned hash(unsigned *uv, int n)
Definition rege_dfa.c:724
#define malloc(a)

References conn, fb(), hash(), len, libpq_append_conn_error(), malloc, and memcpy().

Referenced by build_client_final_message().

◆ pgtls_open_client()

PostgresPollingStatusType pgtls_open_client ( PGconn conn)

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

98{
99 /* First time through? */
100 if (conn->ssl == NULL)
101 {
102 /*
103 * Create a connection-specific SSL object, and load client
104 * certificate, private key, and trusted CA certs.
105 */
106 if (initialize_SSL(conn) != 0)
107 {
108 /* initialize_SSL already put a message in conn->errorMessage */
111 }
112 }
113
114 /* Begin or continue the actual handshake */
115 return open_client_SSL(conn);
116}
static int initialize_SSL(PGconn *conn)
static PostgresPollingStatusType open_client_SSL(PGconn *conn)

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

Referenced by pqsecure_open_client().

◆ pgtls_read()

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

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

120{
121 ssize_t n;
122 int result_errno = 0;
124 int err;
125 unsigned long ecode;
126
127rloop:
128
129 /*
130 * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
131 * queue. In general, the current thread's error queue must be empty
132 * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
133 * not work reliably. Since the possibility exists that other OpenSSL
134 * clients running in the same thread but not under our control will fail
135 * to call ERR_get_error() themselves (after their own I/O operations),
136 * pro-actively clear the per-thread error queue now.
137 */
140 n = SSL_read(conn->ssl, ptr, len);
141 err = SSL_get_error(conn->ssl, n);
142
143 /*
144 * Other clients of OpenSSL may fail to call ERR_get_error(), but we
145 * always do, so as to not cause problems for OpenSSL clients that don't
146 * call ERR_clear_error() defensively. Be sure that this happens by
147 * calling now. SSL_get_error() relies on the OpenSSL per-thread error
148 * queue being intact, so this is the earliest possible point
149 * ERR_get_error() may be called.
150 */
151 ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
152 switch (err)
153 {
154 case SSL_ERROR_NONE:
155 if (n < 0)
156 {
157 /* Not supposed to happen, so we don't translate the msg */
159 "SSL_read failed but did not provide error information\n");
160 /* assume the connection is broken */
162 }
163 break;
165 n = 0;
166 break;
168
169 /*
170 * Returning 0 here would cause caller to wait for read-ready,
171 * which is not correct since what SSL wants is wait for
172 * write-ready. The former could get us stuck in an infinite
173 * wait, so don't risk it; busy-loop instead.
174 */
175 goto rloop;
177 if (n < 0 && SOCK_ERRNO != 0)
178 {
180 if (result_errno == EPIPE ||
182 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
183 "\tThis probably means the server terminated abnormally\n"
184 "\tbefore or while processing the request.");
185 else
186 libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
188 sebuf, sizeof(sebuf)));
189 }
190 else
191 {
192 libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
193 /* assume the connection is broken */
195 n = -1;
196 }
197 break;
198 case SSL_ERROR_SSL:
199 {
200 char *errm = SSLerrmessage(ecode);
201
202 libpq_append_conn_error(conn, "SSL error: %s", errm);
204 /* assume the connection is broken */
206 n = -1;
207 break;
208 }
210
211 /*
212 * Per OpenSSL documentation, this error code is only returned for
213 * a clean connection closure, so we should not report it as a
214 * server crash.
215 */
216 libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
218 n = -1;
219 break;
220 default:
221 libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
222 /* assume the connection is broken */
224 n = -1;
225 break;
226 }
227
228 /* ensure we return the intended errno to caller */
230
231 return n;
232}
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
PQExpBufferData errorMessage
Definition libpq-int.h:686
#define ECONNRESET
Definition win32_port.h:388

References appendPQExpBufferStr(), conn, ECONNRESET, err(), pg_conn::errorMessage, fb(), len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_read().

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

579{
581 int i;
582 int rc = 0;
583 char *host = conn->connhost[conn->whichhost].host;
584 int host_type;
585 bool check_cn = true;
586
587 Assert(host && host[0]); /* should be guaranteed by caller */
588
589 /*
590 * We try to match the NSS behavior here, which is a slight departure from
591 * the spec but seems to make more intuitive sense:
592 *
593 * If connhost contains a DNS name, and the certificate's SANs contain any
594 * dNSName entries, then we'll ignore the Subject Common Name entirely;
595 * otherwise, we fall back to checking the CN. (This behavior matches the
596 * RFC.)
597 *
598 * If connhost contains an IP address, and the SANs contain iPAddress
599 * entries, we again ignore the CN. Otherwise, we allow the CN to match,
600 * EVEN IF there is a dNSName in the SANs. (RFC 6125 prohibits this: "A
601 * client MUST NOT seek a match for a reference identifier of CN-ID if the
602 * presented identifiers include a DNS-ID, SRV-ID, URI-ID, or any
603 * application-specific identifier types supported by the client.")
604 *
605 * NOTE: Prior versions of libpq did not consider iPAddress entries at
606 * all, so this new behavior might break a certificate that has different
607 * IP addresses in the Subject CN and the SANs.
608 */
609 if (is_ip_address(host))
611 else
613
614 /*
615 * First, get the Subject Alternative Names (SANs) from the certificate,
616 * and compare them against the originally given hostname.
617 */
620
621 if (peer_san)
622 {
624
625 for (i = 0; i < san_len; i++)
626 {
628 char *alt_name = NULL;
629
630 if (name->type == host_type)
631 {
632 /*
633 * This SAN is of the same type (IP or DNS) as our host name,
634 * so don't allow a fallback check of the CN.
635 */
636 check_cn = false;
637 }
638
639 if (name->type == GEN_DNS)
640 {
641 (*names_examined)++;
643 name->d.dNSName,
644 &alt_name);
645 }
646 else if (name->type == GEN_IPADD)
647 {
648 (*names_examined)++;
650 name->d.iPAddress,
651 &alt_name);
652 }
653
654 if (alt_name)
655 {
656 if (!*first_name)
658 else
659 free(alt_name);
660 }
661
662 if (rc != 0)
663 {
664 /*
665 * Either we hit an error or a match, and either way we should
666 * not fall back to the CN.
667 */
668 check_cn = false;
669 break;
670 }
671 }
673 }
674
675 /*
676 * If there is no subjectAltName extension of the matching type, check the
677 * Common Name.
678 *
679 * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
680 * dNSName is present, the CN must be ignored. We break this rule if host
681 * is an IP address; see the comment above.)
682 */
683 if (check_cn)
684 {
685 const X509_NAME *subject_name;
686
688 if (subject_name != NULL)
689 {
690 int cn_index;
691
693 NID_commonName, -1);
694 if (cn_index >= 0)
695 {
696 char *common_name = NULL;
697
698 (*names_examined)++;
701 &common_name);
702
703 if (common_name)
704 {
705 if (!*first_name)
707 else
709 }
710 }
711 }
712 }
713
714 return rc;
715}
#define unconstify(underlying_type, expr)
Definition c.h:1384
static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn, const ASN1_STRING *name_entry, char **store_name)
static int openssl_verify_peer_name_matches_certificate_ip(PGconn *conn, ASN1_OCTET_STRING *addr_entry, char **store_name)
static bool is_ip_address(const char *host)
int i
Definition isn.c:77
const char * name

References Assert, conn, pg_conn::connhost, fb(), free, pg_conn_host::host, i, is_ip_address(), name, openssl_verify_peer_name_matches_certificate_ip(), openssl_verify_peer_name_matches_certificate_name(), unconstify, and pg_conn::whichhost.

Referenced by pq_verify_peer_name_matches_certificate().

◆ pgtls_write()

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

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

272{
273 ssize_t n;
274 int result_errno = 0;
276 int err;
277 unsigned long ecode;
278
281 n = SSL_write(conn->ssl, ptr, len);
282 err = SSL_get_error(conn->ssl, n);
283 ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
284 switch (err)
285 {
286 case SSL_ERROR_NONE:
287 if (n < 0)
288 {
289 /* Not supposed to happen, so we don't translate the msg */
291 "SSL_write failed but did not provide error information\n");
292 /* assume the connection is broken */
294 }
295 break;
297
298 /*
299 * Returning 0 here causes caller to wait for write-ready, which
300 * is not really the right thing, but it's the best we can do.
301 */
302 n = 0;
303 break;
305 n = 0;
306 break;
308
309 /*
310 * If errno is still zero then assume it's a read EOF situation,
311 * and report EOF. (This seems possible because SSL_write can
312 * also do reads.)
313 */
314 if (n < 0 && SOCK_ERRNO != 0)
315 {
318 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
319 "\tThis probably means the server terminated abnormally\n"
320 "\tbefore or while processing the request.");
321 else
322 libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
324 sebuf, sizeof(sebuf)));
325 }
326 else
327 {
328 libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
329 /* assume the connection is broken */
331 n = -1;
332 }
333 break;
334 case SSL_ERROR_SSL:
335 {
336 char *errm = SSLerrmessage(ecode);
337
338 libpq_append_conn_error(conn, "SSL error: %s", errm);
340 /* assume the connection is broken */
342 n = -1;
343 break;
344 }
346
347 /*
348 * Per OpenSSL documentation, this error code is only returned for
349 * a clean connection closure, so we should not report it as a
350 * server crash.
351 */
352 libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
354 n = -1;
355 break;
356 default:
357 libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
358 /* assume the connection is broken */
360 n = -1;
361 break;
362 }
363
364 /* ensure we return the intended errno to caller */
366
367 return n;
368}

References appendPQExpBufferStr(), conn, ECONNRESET, err(), pg_conn::errorMessage, fb(), len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_write().

◆ PQdefaultSSLKeyPassHook_OpenSSL()

int PQdefaultSSLKeyPassHook_OpenSSL ( char buf,
int  size,
PGconn conn 
)

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

1937{
1938 if (conn && conn->sslpassword)
1939 {
1940 if (strlen(conn->sslpassword) + 1 > size)
1941 fprintf(stderr, libpq_gettext("WARNING: sslpassword truncated\n"));
1942 strncpy(buf, conn->sslpassword, size);
1943 buf[size - 1] = '\0';
1944 return strlen(buf);
1945 }
1946 else
1947 {
1948 buf[0] = '\0';
1949 return 0;
1950 }
1951}

References buf, conn, fb(), fprintf, libpq_gettext, and pg_conn::sslpassword.

Referenced by PQssl_passwd_cb().

◆ PQgetssl()

void * PQgetssl ( PGconn conn)

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

1659{
1660 if (!conn)
1661 return NULL;
1662 return conn->ssl;
1663}

References conn, and fb().

◆ PQgetSSLKeyPassHook_OpenSSL()

PQsslKeyPassHook_OpenSSL_type PQgetSSLKeyPassHook_OpenSSL ( void  )

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

1955{
1956 return PQsslKeyPassHook;
1957}

References PQsslKeyPassHook.

◆ PQsetSSLKeyPassHook_OpenSSL()

void PQsetSSLKeyPassHook_OpenSSL ( PQsslKeyPassHook_OpenSSL_type  hook)

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

1961{
1962 PQsslKeyPassHook = hook;
1963}

References PQsslKeyPassHook.

◆ PQssl_passwd_cb()

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

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

1972{
1973 PGconn *conn = userdata;
1974
1975 if (PQsslKeyPassHook)
1976 return PQsslKeyPassHook(buf, size, conn);
1977 else
1979}
int PQdefaultSSLKeyPassHook_OpenSSL(char *buf, int size, PGconn *conn)

References buf, conn, fb(), PQdefaultSSLKeyPassHook_OpenSSL(), and PQsslKeyPassHook.

Referenced by initialize_SSL().

◆ PQsslAttribute()

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

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

1704{
1705 if (!conn)
1706 {
1707 /* PQsslAttribute(NULL, "library") reports the default SSL library */
1708 if (strcmp(attribute_name, "library") == 0)
1709 return "OpenSSL";
1710 return NULL;
1711 }
1712
1713 /* All attributes read as NULL for a non-encrypted connection */
1714 if (conn->ssl == NULL)
1715 return NULL;
1716
1717 if (strcmp(attribute_name, "library") == 0)
1718 return "OpenSSL";
1719
1720 if (strcmp(attribute_name, "key_bits") == 0)
1721 {
1722 static char sslbits_str[12];
1723 int sslbits;
1724
1726 snprintf(sslbits_str, sizeof(sslbits_str), "%d", sslbits);
1727 return sslbits_str;
1728 }
1729
1730 if (strcmp(attribute_name, "cipher") == 0)
1731 return SSL_get_cipher(conn->ssl);
1732
1733 if (strcmp(attribute_name, "compression") == 0)
1734 return SSL_get_current_compression(conn->ssl) ? "on" : "off";
1735
1736 if (strcmp(attribute_name, "protocol") == 0)
1737 return SSL_get_version(conn->ssl);
1738
1739 if (strcmp(attribute_name, "alpn") == 0)
1740 {
1741 const unsigned char *data;
1742 unsigned int len;
1743 static char alpn_str[256]; /* alpn doesn't support longer than 255
1744 * bytes */
1745
1747 if (data == NULL || len == 0 || len > sizeof(alpn_str) - 1)
1748 return "";
1750 alpn_str[len] = 0;
1751 return alpn_str;
1752 }
1753
1754 return NULL; /* unknown attribute */
1755}
const void * data

References conn, data, fb(), len, memcpy(), and snprintf.

Referenced by exec_command_conninfo(), print_ssl_library(), and printSSLInfo().

◆ PQsslAttributeNames()

const char *const * PQsslAttributeNames ( PGconn conn)

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

1677{
1678 static const char *const openssl_attrs[] = {
1679 "library",
1680 "key_bits",
1681 "cipher",
1682 "compression",
1683 "protocol",
1684 "alpn",
1685 NULL
1686 };
1687 static const char *const empty_attrs[] = {NULL};
1688
1689 if (!conn)
1690 {
1691 /* Return attributes of default SSL library */
1692 return openssl_attrs;
1693 }
1694
1695 /* No attrs for unencrypted connection */
1696 if (conn->ssl == NULL)
1697 return empty_attrs;
1698
1699 return openssl_attrs;
1700}

References conn, and fb().

◆ PQsslStruct()

void * PQsslStruct ( PGconn conn,
const char struct_name 
)

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

1667{
1668 if (!conn)
1669 return NULL;
1670 if (strcmp(struct_name, "OpenSSL") == 0)
1671 return conn->ssl;
1672 return NULL;
1673}

References conn, and fb().

◆ ssl_protocol_version_to_openssl()

static int ssl_protocol_version_to_openssl ( const char protocol)
static

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

1993{
1994 if (pg_strcasecmp("TLSv1", protocol) == 0)
1995 return TLS1_VERSION;
1996
1997#ifdef TLS1_1_VERSION
1998 if (pg_strcasecmp("TLSv1.1", protocol) == 0)
1999 return TLS1_1_VERSION;
2000#endif
2001
2002#ifdef TLS1_2_VERSION
2003 if (pg_strcasecmp("TLSv1.2", protocol) == 0)
2004 return TLS1_2_VERSION;
2005#endif
2006
2007#ifdef TLS1_3_VERSION
2008 if (pg_strcasecmp("TLSv1.3", protocol) == 0)
2009 return TLS1_3_VERSION;
2010#endif
2011
2012 return -1;
2013}
int pg_strcasecmp(const char *s1, const char *s2)

References fb(), and pg_strcasecmp().

Referenced by initialize_SSL().

◆ ssl_set_pgconn_bio()

static int ssl_set_pgconn_bio ( PGconn conn)
static

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

1911{
1912 BIO *bio;
1914
1916 if (bio_method == NULL)
1917 return 0;
1918
1920 if (bio == NULL)
1921 return 0;
1922
1924 BIO_set_init(bio, 1);
1925
1926 SSL_set_bio(conn->ssl, bio, bio);
1927 return 1;
1928}
static BIO_METHOD * pgconn_bio_method(void)

References conn, fb(), and pgconn_bio_method().

Referenced by initialize_SSL().

◆ SSLerrfree()

static void SSLerrfree ( char buf)
static

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

1645{
1646 if (buf != ssl_nomem)
1647 free(buf);
1648}
static char ssl_nomem[]

References buf, free, and ssl_nomem.

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

◆ SSLerrmessage()

static char * SSLerrmessage ( unsigned long  ecode)
static

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

1587{
1588 const char *errreason;
1589 char *errbuf;
1590
1591 errbuf = malloc(SSL_ERR_LEN);
1592 if (!errbuf)
1593 return ssl_nomem;
1594 if (ecode == 0)
1595 {
1596 snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("no SSL error reported"));
1597 return errbuf;
1598 }
1599 errreason = ERR_reason_error_string(ecode);
1600 if (errreason != NULL)
1601 {
1602 strlcpy(errbuf, errreason, SSL_ERR_LEN);
1603 return errbuf;
1604 }
1605
1606 /*
1607 * Server aborted the connection with TLS "no_application_protocol" alert.
1608 * The ERR_reason_error_string() function doesn't give any error string
1609 * for that for some reason, so do it ourselves. See
1610 * https://github.com/openssl/openssl/issues/24300. This is available in
1611 * OpenSSL 1.1.0 and later, as well as in LibreSSL 3.4.3 (OpenBSD 7.0) and
1612 * later.
1613 */
1614#ifdef SSL_AD_NO_APPLICATION_PROTOCOL
1615 if (ERR_GET_LIB(ecode) == ERR_LIB_SSL &&
1617 {
1618 snprintf(errbuf, SSL_ERR_LEN, "no application protocol");
1619 return errbuf;
1620 }
1621#endif
1622
1623 /*
1624 * In OpenSSL 3.0.0 and later, ERR_reason_error_string does not map system
1625 * errno values anymore. (See OpenSSL source code for the explanation.)
1626 * We can cover that shortcoming with this bit of code. Older OpenSSL
1627 * versions don't have the ERR_SYSTEM_ERROR macro, but that's okay because
1628 * they don't have the shortcoming either.
1629 */
1630#ifdef ERR_SYSTEM_ERROR
1632 {
1634 return errbuf;
1635 }
1636#endif
1637
1638 /* No choice but to report the numeric ecode */
1639 snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("SSL error code %lu"), ecode);
1640 return errbuf;
1641}
#define SSL_ERR_LEN

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

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

◆ verify_cb()

static int verify_cb ( int  ok,
X509_STORE_CTX ctx 
)
static

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

462{
463 return ok;
464}

References fb().

Referenced by initialize_SSL().

Variable Documentation

◆ alpn_protos

unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR
static

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

Referenced by initialize_SSL().

◆ pgconn_bio_method_ptr

BIO_METHOD* pgconn_bio_method_ptr
static

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

Referenced by pgconn_bio_method().

◆ PQsslKeyPassHook

◆ ssl_config_mutex

pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER
static

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

Referenced by pgconn_bio_method().

◆ ssl_nomem

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

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

Referenced by SSLerrfree(), and SSLerrmessage().