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 "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)
 
bool pgtls_read_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 1552 of file fe-secure-openssl.c.

Function Documentation

◆ initialize_SSL()

static int initialize_SSL ( PGconn conn)
static

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

741{
743 struct stat buf;
744 char homedir[MAXPGPATH];
745 char fnbuf[MAXPGPATH];
747 bool have_homedir;
748 bool have_cert;
749 bool have_rootcert;
750
751 /*
752 * We'll need the home directory if any of the relevant parameters are
753 * defaulted. If pqGetHomeDirectory fails, act as though none of the
754 * files could be found.
755 */
756 if (!(conn->sslcert && strlen(conn->sslcert) > 0) ||
757 !(conn->sslkey && strlen(conn->sslkey) > 0) ||
758 !(conn->sslrootcert && strlen(conn->sslrootcert) > 0) ||
759 !((conn->sslcrl && strlen(conn->sslcrl) > 0) ||
760 (conn->sslcrldir && strlen(conn->sslcrldir) > 0)))
762 else /* won't need it */
763 have_homedir = false;
764
765 /*
766 * Create a new SSL_CTX object.
767 *
768 * We used to share a single SSL_CTX between all connections, but it was
769 * complicated if connections used different certificates. So now we
770 * create a separate context for each connection, and accept the overhead.
771 */
773 if (!SSL_context)
774 {
776
777 libpq_append_conn_error(conn, "could not create SSL context: %s", err);
779 return -1;
780 }
781
782 /*
783 * Delegate the client cert password prompt to the libpq wrapper callback
784 * if any is defined.
785 *
786 * If the application hasn't installed its own and the sslpassword
787 * parameter is non-null, we install ours now to make sure we supply
788 * PGconn->sslpassword to OpenSSL instead of letting it prompt on stdin.
789 *
790 * This will replace OpenSSL's default PEM_def_callback (which prompts on
791 * stdin), but we're only setting it for this SSL context so it's
792 * harmless.
793 */
795 || (conn->sslpassword && strlen(conn->sslpassword) > 0))
796 {
799 }
800
801#ifdef HAVE_SSL_CTX_SET_CERT_CB
802 /* Set up a certificate selection callback. */
804#endif
805
806 /* Disable old protocol versions */
808
809 /* Set the minimum and maximum protocol versions if necessary */
812 {
813 int ssl_min_ver;
814
816
817 if (ssl_min_ver == -1)
818 {
819 libpq_append_conn_error(conn, "invalid value \"%s\" for minimum SSL protocol version",
822 return -1;
823 }
824
826 {
828
829 libpq_append_conn_error(conn, "could not set minimum SSL protocol version: %s", err);
832 return -1;
833 }
834 }
835
838 {
839 int ssl_max_ver;
840
842
843 if (ssl_max_ver == -1)
844 {
845 libpq_append_conn_error(conn, "invalid value \"%s\" for maximum SSL protocol version",
848 return -1;
849 }
850
852 {
854
855 libpq_append_conn_error(conn, "could not set maximum SSL protocol version: %s", err);
858 return -1;
859 }
860 }
861
862 /*
863 * Disable OpenSSL's moving-write-buffer sanity check, because it causes
864 * unnecessary failures in nonblocking send cases.
865 */
867
868 /*
869 * If the root cert file exists, load it so we can perform certificate
870 * verification. If sslmode is "verify-full" we will also do further
871 * verification after the connection has been completed.
872 */
873 if (conn->sslrootcert && strlen(conn->sslrootcert) > 0)
874 strlcpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
875 else if (have_homedir)
876 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
877 else
878 fnbuf[0] = '\0';
879
880 if (strcmp(fnbuf, "system") == 0)
881 {
882 /*
883 * The "system" sentinel value indicates that we should load whatever
884 * root certificates are installed for use by OpenSSL; these locations
885 * differ by platform. Note that the default system locations may be
886 * further overridden by the SSL_CERT_DIR and SSL_CERT_FILE
887 * environment variables.
888 */
890 {
892
893 libpq_append_conn_error(conn, "could not load system root certificate paths: %s",
894 err);
897 return -1;
898 }
899 have_rootcert = true;
900 }
901 else if (fnbuf[0] != '\0' &&
902 stat(fnbuf, &buf) == 0)
903 {
905
907 {
909
910 libpq_append_conn_error(conn, "could not read root certificate file \"%s\": %s",
911 fnbuf, err);
914 return -1;
915 }
916
918 {
919 char *fname = NULL;
920 char *dname = NULL;
921
922 if (conn->sslcrl && strlen(conn->sslcrl) > 0)
923 fname = conn->sslcrl;
924 if (conn->sslcrldir && strlen(conn->sslcrldir) > 0)
926
927 /* defaults to use the default CRL file */
928 if (!fname && !dname && have_homedir)
929 {
930 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE);
931 fname = fnbuf;
932 }
933
934 /* Set the flags to check against the complete CRL chain */
935 if ((fname || dname) &&
937 {
940 }
941
942 /* if not found, silently ignore; we do not require CRL */
944 }
945 have_rootcert = true;
946 }
947 else
948 {
949 /*
950 * stat() failed; assume root file doesn't exist. If sslmode is
951 * verify-ca or verify-full, this is an error. Otherwise, continue
952 * without performing any server cert verification.
953 */
954 if (conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */
955 {
956 /*
957 * The only way to reach here with an empty filename is if
958 * pqGetHomeDirectory failed. That's a sufficiently unusual case
959 * that it seems worth having a specialized error message for it.
960 */
961 if (fnbuf[0] == '\0')
962 libpq_append_conn_error(conn, "could not get home directory to locate root certificate file\n"
963 "Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification.");
964 else
965 libpq_append_conn_error(conn, "root certificate file \"%s\" does not exist\n"
966 "Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification.", fnbuf);
968 return -1;
969 }
970 have_rootcert = false;
971 }
972
973 /* Read the client certificate file */
974 if (conn->sslcert && strlen(conn->sslcert) > 0)
975 strlcpy(fnbuf, conn->sslcert, sizeof(fnbuf));
976 else if (have_homedir)
977 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
978 else
979 fnbuf[0] = '\0';
980
981 if (conn->sslcertmode[0] == 'd') /* disable */
982 {
983 /* don't send a client cert even if we have one */
984 have_cert = false;
985 }
986 else if (fnbuf[0] == '\0')
987 {
988 /* no home directory, proceed without a client cert */
989 have_cert = false;
990 }
991 else if (stat(fnbuf, &buf) != 0)
992 {
993 /*
994 * If file is not present, just go on without a client cert; server
995 * might or might not accept the connection. Any other error,
996 * however, is grounds for complaint.
997 */
998 if (errno != ENOENT && errno != ENOTDIR)
999 {
1000 libpq_append_conn_error(conn, "could not open certificate file \"%s\": %s",
1001 fnbuf, strerror_r(errno, sebuf, sizeof(sebuf)));
1003 return -1;
1004 }
1005 have_cert = false;
1006 }
1007 else
1008 {
1009 /*
1010 * Cert file exists, so load it. Since OpenSSL doesn't provide the
1011 * equivalent of "SSL_use_certificate_chain_file", we have to load it
1012 * into the SSL context, rather than the SSL object.
1013 */
1015 {
1016 char *err = SSLerrmessage(ERR_get_error());
1017
1018 libpq_append_conn_error(conn, "could not read certificate file \"%s\": %s",
1019 fnbuf, err);
1020 SSLerrfree(err);
1022 return -1;
1023 }
1024
1025 /* need to load the associated private key, too */
1026 have_cert = true;
1027 }
1028
1029 /*
1030 * The SSL context is now loaded with the correct root and client
1031 * certificates. Create a connection-specific SSL object. The private key
1032 * is loaded directly into the SSL object. (We could load the private key
1033 * into the context, too, but we have done it this way historically, and
1034 * it doesn't really matter.)
1035 */
1036 if (!(conn->ssl = SSL_new(SSL_context)) ||
1037 !SSL_set_app_data(conn->ssl, conn) ||
1039 {
1040 char *err = SSLerrmessage(ERR_get_error());
1041
1042 libpq_append_conn_error(conn, "could not establish SSL connection: %s", err);
1043 SSLerrfree(err);
1045 return -1;
1046 }
1047 conn->ssl_in_use = true;
1048
1049 /*
1050 * If SSL key logging is requested, set up the callback if a compatible
1051 * version of OpenSSL is used and libpq was compiled to support it.
1052 */
1054 {
1055#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK
1057#else
1058#ifdef LIBRESSL_VERSION_NUMBER
1059 fprintf(stderr, libpq_gettext("WARNING: sslkeylogfile support requires OpenSSL\n"));
1060#else
1061 fprintf(stderr, libpq_gettext("WARNING: libpq was not built with sslkeylogfile support\n"));
1062#endif
1063#endif
1064 }
1065
1066 /*
1067 * SSL contexts are reference counted by OpenSSL. We can free it as soon
1068 * as we have created the SSL object, and it will stick around for as long
1069 * as it's actually needed.
1070 */
1072 SSL_context = NULL;
1073
1074 /*
1075 * Set Server Name Indication (SNI), if enabled by connection parameters.
1076 * Per RFC 6066, do not set it if the host is a literal IP address (IPv4
1077 * or IPv6).
1078 */
1079 if (conn->sslsni && conn->sslsni[0] == '1')
1080 {
1081 const char *host = conn->connhost[conn->whichhost].host;
1082
1083 if (host && host[0] &&
1084 !(strspn(host, "0123456789.") == strlen(host) ||
1085 strchr(host, ':')))
1086 {
1087 if (SSL_set_tlsext_host_name(conn->ssl, host) != 1)
1088 {
1089 char *err = SSLerrmessage(ERR_get_error());
1090
1091 libpq_append_conn_error(conn, "could not set SSL Server Name Indication (SNI): %s", err);
1092 SSLerrfree(err);
1093 return -1;
1094 }
1095 }
1096 }
1097
1098 /* Set ALPN */
1099 {
1100 int retval;
1101
1102 retval = SSL_set_alpn_protos(conn->ssl, alpn_protos, sizeof(alpn_protos));
1103
1104 if (retval != 0)
1105 {
1106 char *err = SSLerrmessage(ERR_get_error());
1107
1108 libpq_append_conn_error(conn, "could not set SSL ALPN extension: %s", err);
1109 SSLerrfree(err);
1110 return -1;
1111 }
1112 }
1113
1114 /*
1115 * Read the SSL key. If a key is specified, treat it as an engine:key
1116 * combination if there is colon present - we don't support files with
1117 * colon in the name. The exception is if the second character is a colon,
1118 * in which case it can be a Windows filename with drive specification.
1119 */
1120 if (have_cert && conn->sslkey && strlen(conn->sslkey) > 0)
1121 {
1122#ifdef USE_SSL_ENGINE
1123 if (strchr(conn->sslkey, ':')
1124#ifdef WIN32
1125 && conn->sslkey[1] != ':'
1126#endif
1127 )
1128 {
1129 /* Colon, but not in second character, treat as engine:key */
1130 char *engine_str = strdup(conn->sslkey);
1131 char *engine_colon;
1132 EVP_PKEY *pkey;
1133
1134 if (engine_str == NULL)
1135 {
1136 libpq_append_conn_error(conn, "out of memory");
1137 return -1;
1138 }
1139
1140 /* cannot return NULL because we already checked before strdup */
1142
1143 *engine_colon = '\0'; /* engine_str now has engine name */
1144 engine_colon++; /* engine_colon now has key name */
1145
1146 conn->engine = ENGINE_by_id(engine_str);
1147 if (conn->engine == NULL)
1148 {
1149 char *err = SSLerrmessage(ERR_get_error());
1150
1151 libpq_append_conn_error(conn, "could not load SSL engine \"%s\": %s",
1152 engine_str, err);
1153 SSLerrfree(err);
1155 return -1;
1156 }
1157
1158 if (ENGINE_init(conn->engine) == 0)
1159 {
1160 char *err = SSLerrmessage(ERR_get_error());
1161
1162 libpq_append_conn_error(conn, "could not initialize SSL engine \"%s\": %s",
1163 engine_str, err);
1164 SSLerrfree(err);
1165 ENGINE_free(conn->engine);
1166 conn->engine = NULL;
1168 return -1;
1169 }
1170
1172 NULL, NULL);
1173 if (pkey == NULL)
1174 {
1175 char *err = SSLerrmessage(ERR_get_error());
1176
1177 libpq_append_conn_error(conn, "could not read private SSL key \"%s\" from engine \"%s\": %s",
1179 SSLerrfree(err);
1180 ENGINE_finish(conn->engine);
1181 ENGINE_free(conn->engine);
1182 conn->engine = NULL;
1184 return -1;
1185 }
1186 if (SSL_use_PrivateKey(conn->ssl, pkey) != 1)
1187 {
1188 char *err = SSLerrmessage(ERR_get_error());
1189
1190 libpq_append_conn_error(conn, "could not load private SSL key \"%s\" from engine \"%s\": %s",
1192 SSLerrfree(err);
1193 ENGINE_finish(conn->engine);
1194 ENGINE_free(conn->engine);
1195 conn->engine = NULL;
1197 return -1;
1198 }
1199
1201
1202 fnbuf[0] = '\0'; /* indicate we're not going to load from a
1203 * file */
1204 }
1205 else
1206#endif /* USE_SSL_ENGINE */
1207 {
1208 /* PGSSLKEY is not an engine, treat it as a filename */
1209 strlcpy(fnbuf, conn->sslkey, sizeof(fnbuf));
1210 }
1211 }
1212 else if (have_homedir)
1213 {
1214 /* No PGSSLKEY specified, load default file */
1215 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
1216 }
1217 else
1218 fnbuf[0] = '\0';
1219
1220 if (have_cert && fnbuf[0] != '\0')
1221 {
1222 /* read the client key from file */
1223
1224 if (stat(fnbuf, &buf) != 0)
1225 {
1226 if (errno == ENOENT)
1227 libpq_append_conn_error(conn, "certificate present, but not private key file \"%s\"",
1228 fnbuf);
1229 else
1230 libpq_append_conn_error(conn, "could not stat private key file \"%s\": %m",
1231 fnbuf);
1232 return -1;
1233 }
1234
1235 /* Key file must be a regular file */
1236 if (!S_ISREG(buf.st_mode))
1237 {
1238 libpq_append_conn_error(conn, "private key file \"%s\" is not a regular file",
1239 fnbuf);
1240 return -1;
1241 }
1242
1243 /*
1244 * Refuse to load world-readable key files. We accept root-owned
1245 * files with mode 0640 or less, so that we can access system-wide
1246 * certificates if we have a supplementary group membership that
1247 * allows us to read 'em. For files with non-root ownership, require
1248 * mode 0600 or less. We need not check the file's ownership exactly;
1249 * if we're able to read it despite it having such restrictive
1250 * permissions, it must have the right ownership.
1251 *
1252 * Note: be very careful about tightening these rules. Some people
1253 * expect, for example, that a client process running as root should
1254 * be able to use a non-root-owned key file.
1255 *
1256 * Note that roughly similar checks are performed in
1257 * src/backend/libpq/be-secure-common.c so any changes here may need
1258 * to be made there as well. However, this code caters for the case
1259 * of current user == root, while that code does not.
1260 *
1261 * Ideally we would do similar permissions checks on Windows, but it
1262 * is not clear how that would work since Unix-style permissions may
1263 * not be available.
1264 */
1265#if !defined(WIN32) && !defined(__CYGWIN__)
1266 if (buf.st_uid == 0 ?
1267 buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO) :
1268 buf.st_mode & (S_IRWXG | S_IRWXO))
1269 {
1271 "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",
1272 fnbuf);
1273 return -1;
1274 }
1275#endif
1276
1278 {
1279 char *err = SSLerrmessage(ERR_get_error());
1280
1281 /*
1282 * We'll try to load the file in DER (binary ASN.1) format, and if
1283 * that fails too, report the original error. This could mask
1284 * issues where there's something wrong with a DER-format cert,
1285 * but we'd have to duplicate openssl's format detection to be
1286 * smarter than this. We can't just probe for a leading -----BEGIN
1287 * because PEM can have leading non-matching lines and blanks.
1288 * OpenSSL doesn't expose its get_name(...) and its PEM routines
1289 * don't differentiate between failure modes in enough detail to
1290 * let us tell the difference between "not PEM, try DER" and
1291 * "wrong password".
1292 */
1294 {
1295 libpq_append_conn_error(conn, "could not load private key file \"%s\": %s",
1296 fnbuf, err);
1297 SSLerrfree(err);
1298 return -1;
1299 }
1300
1301 SSLerrfree(err);
1302 }
1303 }
1304
1305 /* verify that the cert and key go together */
1306 if (have_cert &&
1307 SSL_check_private_key(conn->ssl) != 1)
1308 {
1309 char *err = SSLerrmessage(ERR_get_error());
1310
1311 libpq_append_conn_error(conn, "certificate does not match private key file \"%s\": %s",
1312 fnbuf, err);
1313 SSLerrfree(err);
1314 return -1;
1315 }
1316
1317 /*
1318 * If a root cert was loaded, also set our certificate verification
1319 * callback.
1320 */
1321 if (have_rootcert)
1323
1324 /*
1325 * Set compression option if necessary.
1326 */
1327 if (conn->sslcompression && conn->sslcompression[0] == '0')
1329 else
1331
1332 return 0;
1333}
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:1404
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:297
#define stat
Definition win32_port.h:74
#define S_IRWXG
Definition win32_port.h:300
#define S_IRWXO
Definition win32_port.h:312
#define S_ISREG(m)
Definition win32_port.h:318
#define S_IWGRP
Definition win32_port.h:294

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

526{
527 struct in_addr dummy4;
528#ifdef HAVE_INET_PTON
529 struct in6_addr dummy6;
530#endif
531
532 return inet_aton(host, &dummy4)
533#ifdef HAVE_INET_PTON
534 || (inet_pton(AF_INET6, host, &dummy6) == 1)
535#endif
536 ;
537}
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 1339 of file fe-secure-openssl.c.

1340{
1341 int r;
1342
1343 SOCK_ERRNO_SET(0);
1345 r = SSL_connect(conn->ssl);
1346 if (r <= 0)
1347 {
1348 int save_errno = SOCK_ERRNO;
1349 int err = SSL_get_error(conn->ssl, r);
1350 unsigned long ecode;
1351
1352 ecode = ERR_get_error();
1353 switch (err)
1354 {
1356 return PGRES_POLLING_READING;
1357
1359 return PGRES_POLLING_WRITING;
1360
1361 case SSL_ERROR_SYSCALL:
1362 {
1364 unsigned long vcode;
1365
1367
1368 /*
1369 * If we get an X509 error here for failing to load the
1370 * local issuer cert, without an error in the socket layer
1371 * it means that verification failed due to a missing
1372 * system CA pool without it being a protocol error. We
1373 * inspect the sslrootcert setting to ensure that the user
1374 * was using the system CA pool. For other errors, log
1375 * them using the normal SYSCALL logging.
1376 */
1377 if (save_errno == 0 &&
1379 strcmp(conn->sslrootcert, "system") == 0)
1380 libpq_append_conn_error(conn, "SSL error: certificate verify failed: %s",
1382 else if (r == -1 && save_errno != 0)
1383 libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
1384 SOCK_STRERROR(save_errno, sebuf, sizeof(sebuf)));
1385 else
1386 libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
1388 return PGRES_POLLING_FAILED;
1389 }
1390 case SSL_ERROR_SSL:
1391 {
1392 char *err = SSLerrmessage(ecode);
1393
1394 libpq_append_conn_error(conn, "SSL error: %s", err);
1395 SSLerrfree(err);
1396 switch (ERR_GET_REASON(ecode))
1397 {
1398 /*
1399 * UNSUPPORTED_PROTOCOL, WRONG_VERSION_NUMBER, and
1400 * TLSV1_ALERT_PROTOCOL_VERSION have been observed
1401 * when trying to communicate with an old OpenSSL
1402 * library, or when the client and server specify
1403 * disjoint protocol ranges.
1404 * NO_PROTOCOLS_AVAILABLE occurs if there's a
1405 * local misconfiguration (which can happen
1406 * despite our checks, if openssl.cnf injects a
1407 * limit we didn't account for). It's not very
1408 * clear what would make OpenSSL return the other
1409 * codes listed here, but a hint about protocol
1410 * versions seems like it's appropriate for all.
1411 */
1421#ifdef SSL_R_VERSION_TOO_HIGH
1424#endif
1425 libpq_append_conn_error(conn, "This may indicate that the server does not support any SSL protocol version between %s and %s.",
1432 break;
1433 default:
1434 break;
1435 }
1437 return PGRES_POLLING_FAILED;
1438 }
1439
1440 default:
1441 libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
1443 return PGRES_POLLING_FAILED;
1444 }
1445 }
1446
1447 /* ALPN is mandatory with direct SSL connections */
1448 if (conn->current_enc_method == ENC_SSL && conn->sslnegotiation[0] == 'd')
1449 {
1450 const unsigned char *selected;
1451 unsigned int len;
1452
1453 SSL_get0_alpn_selected(conn->ssl, &selected, &len);
1454
1455 if (selected == NULL)
1456 {
1457 libpq_append_conn_error(conn, "direct SSL connection was established without ALPN protocol negotiation extension");
1459 return PGRES_POLLING_FAILED;
1460 }
1461
1462 /*
1463 * We only support one protocol so that's what the negotiation should
1464 * always choose, but doesn't hurt to check.
1465 */
1466 if (len != strlen(PG_ALPN_PROTOCOL) ||
1468 {
1469 libpq_append_conn_error(conn, "SSL connection was established with unexpected ALPN protocol");
1471 return PGRES_POLLING_FAILED;
1472 }
1473 }
1474
1475 /*
1476 * We already checked the server certificate in initialize_SSL() using
1477 * SSL_CTX_set_verify(), if root.crt exists.
1478 */
1479
1480 /* get server certificate */
1481 conn->peer = SSL_get_peer_certificate(conn->ssl);
1482 if (conn->peer == NULL)
1483 {
1484 char *err = SSLerrmessage(ERR_get_error());
1485
1486 libpq_append_conn_error(conn, "certificate could not be obtained: %s", err);
1487 SSLerrfree(err);
1489 return PGRES_POLLING_FAILED;
1490 }
1491
1493 {
1495 return PGRES_POLLING_FAILED;
1496 }
1497
1498 /* SSL handshake is complete */
1499 return PGRES_POLLING_OK;
1500}
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:981
#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 500 of file fe-secure-openssl.c.

503{
504 int len;
505 const unsigned char *addrdata;
506
507 /* Should not happen... */
508 if (addr_entry == NULL)
509 {
510 libpq_append_conn_error(conn, "SSL certificate's address entry is missing");
511 return -1;
512 }
513
514 /*
515 * GEN_IPADD is an OCTET STRING containing an IP address in network byte
516 * order.
517 */
520
522}
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 470 of file fe-secure-openssl.c.

473{
474 int len;
475 const unsigned char *namedata;
476
477 /* Should not happen... */
478 if (name_entry == NULL)
479 {
480 libpq_append_conn_error(conn, "SSL certificate's name entry is missing");
481 return -1;
482 }
483
484 /*
485 * GEN_DNS can be only IA5String, equivalent to US ASCII.
486 */
489
490 /* OK to cast from unsigned to plain char, since it's all ASCII. */
492}
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 1804 of file fe-secure-openssl.c.

1805{
1806 long res;
1807 PGconn *conn = (PGconn *) BIO_get_data(h);
1808
1809 switch (cmd)
1810 {
1811 case BIO_CTRL_EOF:
1812
1813 /*
1814 * This should not be needed. pgconn_bio_read already has a way to
1815 * signal EOF to OpenSSL. However, OpenSSL made an undocumented,
1816 * backwards-incompatible change and now expects EOF via BIO_ctrl.
1817 * See https://github.com/openssl/openssl/issues/8208
1818 */
1819 res = conn->last_read_was_eof;
1820 break;
1821 case BIO_CTRL_FLUSH:
1822 /* libssl expects all BIOs to support BIO_flush. */
1823 res = 1;
1824 break;
1825 default:
1826 res = 0;
1827 break;
1828 }
1829
1830 return res;
1831}
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 1834 of file fe-secure-openssl.c.

1835{
1836 BIO_METHOD *res;
1837
1839 return NULL;
1840
1842
1844 {
1845 int my_bio_index;
1846
1848 if (my_bio_index == -1)
1849 goto err;
1851 res = BIO_meth_new(my_bio_index, "libpq socket");
1852 if (!res)
1853 goto err;
1854
1855 /*
1856 * As of this writing, these functions never fail. But check anyway,
1857 * like OpenSSL's own examples do.
1858 */
1862 {
1863 goto err;
1864 }
1865 }
1866
1869 return res;
1870
1871err:
1872 if (res)
1873 BIO_meth_free(res);
1875 return NULL;
1876}
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 1739 of file fe-secure-openssl.c.

1740{
1741 PGconn *conn = (PGconn *) BIO_get_data(h);
1742 int res;
1743
1744 res = pqsecure_raw_read(conn, buf, size);
1746 conn->last_read_was_eof = res == 0;
1747 if (res < 0)
1748 {
1749 /* If we were interrupted, tell caller to retry */
1750 switch (SOCK_ERRNO)
1751 {
1752#ifdef EAGAIN
1753 case EAGAIN:
1754#endif
1755#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
1756 case EWOULDBLOCK:
1757#endif
1758 case EINTR:
1760 break;
1761
1762 default:
1763 break;
1764 }
1765 }
1766
1767 if (res > 0)
1769
1770 return res;
1771}
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:361
#define EWOULDBLOCK
Definition win32_port.h:367
#define EAGAIN
Definition win32_port.h:359

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

1775{
1776 int res;
1777
1778 res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
1780 if (res < 0)
1781 {
1782 /* If we were interrupted, tell caller to retry */
1783 switch (SOCK_ERRNO)
1784 {
1785#ifdef EAGAIN
1786 case EAGAIN:
1787#endif
1788#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
1789 case EWOULDBLOCK:
1790#endif
1791 case EINTR:
1793 break;
1794
1795 default:
1796 break;
1797 }
1798 }
1799
1800 return res;
1801}
ssize_t pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
Definition fe-secure.c:316

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

Referenced by pgconn_bio_method().

◆ pgtls_close()

void pgtls_close ( PGconn conn)

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

1504{
1505 if (conn->ssl_in_use)
1506 {
1507 if (conn->ssl)
1508 {
1509 /*
1510 * We can't destroy everything SSL-related here due to the
1511 * possible later calls to OpenSSL routines which may need our
1512 * thread callbacks, so set a flag here and check at the end.
1513 */
1514
1515 SSL_shutdown(conn->ssl);
1516 SSL_free(conn->ssl);
1517 conn->ssl = NULL;
1518 conn->ssl_in_use = false;
1519 conn->ssl_handshake_started = false;
1520 }
1521
1522 if (conn->peer)
1523 {
1524 X509_free(conn->peer);
1525 conn->peer = NULL;
1526 }
1527
1528#ifdef USE_SSL_ENGINE
1529 if (conn->engine)
1530 {
1531 ENGINE_finish(conn->engine);
1532 ENGINE_free(conn->engine);
1533 conn->engine = NULL;
1534 }
1535#endif
1536 }
1537}

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

341{
343 const EVP_MD *algo_type;
344 unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
345 unsigned int hash_size;
346 int algo_nid;
347 char *cert_hash;
348
349 *len = 0;
350
351 if (!conn->peer)
352 return NULL;
353
354 peer_cert = conn->peer;
355
356 /*
357 * Get the signature algorithm of the certificate to determine the hash
358 * algorithm to use for the result. Prefer X509_get_signature_info(),
359 * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
360 */
361#if HAVE_X509_GET_SIGNATURE_INFO
363#else
365 &algo_nid, NULL))
366#endif
367 {
368 libpq_append_conn_error(conn, "could not determine server certificate signature algorithm");
369 return NULL;
370 }
371
372 /*
373 * The TLS server's certificate bytes need to be hashed with SHA-256 if
374 * its signature algorithm is MD5 or SHA-1 as per RFC 5929
375 * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
376 * is used, the same hash as the signature algorithm is used.
377 */
378 switch (algo_nid)
379 {
380 case NID_md5:
381 case NID_sha1:
383 break;
384 default:
386 if (algo_type == NULL)
387 {
388 libpq_append_conn_error(conn, "could not find digest for NID %s",
390 return NULL;
391 }
392 break;
393 }
394
396 {
397 libpq_append_conn_error(conn, "could not generate peer certificate hash");
398 return NULL;
399 }
400
401 /* save result */
403 if (cert_hash == NULL)
404 {
405 libpq_append_conn_error(conn, "out of memory");
406 return NULL;
407 }
409 *len = hash_size;
410
411 return cert_hash;
412}
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 96 of file fe-secure-openssl.c.

97{
98 /* First time through? */
99 if (conn->ssl == NULL)
100 {
101 /*
102 * Create a connection-specific SSL object, and load client
103 * certificate, private key, and trusted CA certs.
104 */
105 if (initialize_SSL(conn) != 0)
106 {
107 /* initialize_SSL already put a message in conn->errorMessage */
110 }
111 }
112
113 /* Begin or continue the actual handshake */
114 return open_client_SSL(conn);
115}
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 118 of file fe-secure-openssl.c.

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

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_read_pending()

bool pgtls_read_pending ( PGconn conn)

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

235{
236 return SSL_pending(conn->ssl) > 0;
237}

References conn, and fb().

Referenced by pqSocketCheck().

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

548{
550 int i;
551 int rc = 0;
552 char *host = conn->connhost[conn->whichhost].host;
553 int host_type;
554 bool check_cn = true;
555
556 Assert(host && host[0]); /* should be guaranteed by caller */
557
558 /*
559 * We try to match the NSS behavior here, which is a slight departure from
560 * the spec but seems to make more intuitive sense:
561 *
562 * If connhost contains a DNS name, and the certificate's SANs contain any
563 * dNSName entries, then we'll ignore the Subject Common Name entirely;
564 * otherwise, we fall back to checking the CN. (This behavior matches the
565 * RFC.)
566 *
567 * If connhost contains an IP address, and the SANs contain iPAddress
568 * entries, we again ignore the CN. Otherwise, we allow the CN to match,
569 * EVEN IF there is a dNSName in the SANs. (RFC 6125 prohibits this: "A
570 * client MUST NOT seek a match for a reference identifier of CN-ID if the
571 * presented identifiers include a DNS-ID, SRV-ID, URI-ID, or any
572 * application-specific identifier types supported by the client.")
573 *
574 * NOTE: Prior versions of libpq did not consider iPAddress entries at
575 * all, so this new behavior might break a certificate that has different
576 * IP addresses in the Subject CN and the SANs.
577 */
578 if (is_ip_address(host))
580 else
582
583 /*
584 * First, get the Subject Alternative Names (SANs) from the certificate,
585 * and compare them against the originally given hostname.
586 */
589
590 if (peer_san)
591 {
593
594 for (i = 0; i < san_len; i++)
595 {
597 char *alt_name = NULL;
598
599 if (name->type == host_type)
600 {
601 /*
602 * This SAN is of the same type (IP or DNS) as our host name,
603 * so don't allow a fallback check of the CN.
604 */
605 check_cn = false;
606 }
607
608 if (name->type == GEN_DNS)
609 {
610 (*names_examined)++;
612 name->d.dNSName,
613 &alt_name);
614 }
615 else if (name->type == GEN_IPADD)
616 {
617 (*names_examined)++;
619 name->d.iPAddress,
620 &alt_name);
621 }
622
623 if (alt_name)
624 {
625 if (!*first_name)
627 else
628 free(alt_name);
629 }
630
631 if (rc != 0)
632 {
633 /*
634 * Either we hit an error or a match, and either way we should
635 * not fall back to the CN.
636 */
637 check_cn = false;
638 break;
639 }
640 }
642 }
643
644 /*
645 * If there is no subjectAltName extension of the matching type, check the
646 * Common Name.
647 *
648 * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
649 * dNSName is present, the CN must be ignored. We break this rule if host
650 * is an IP address; see the comment above.)
651 */
652 if (check_cn)
653 {
654 const X509_NAME *subject_name;
655
657 if (subject_name != NULL)
658 {
659 int cn_index;
660
662 NID_commonName, -1);
663 if (cn_index >= 0)
664 {
665 char *common_name = NULL;
666
667 (*names_examined)++;
670 &common_name);
671
672 if (common_name)
673 {
674 if (!*first_name)
676 else
678 }
679 }
680 }
681 }
682
683 return rc;
684}
#define unconstify(underlying_type, expr)
Definition c.h:1325
#define Assert(condition)
Definition c.h:943
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 240 of file fe-secure-openssl.c.

241{
242 ssize_t n;
243 int result_errno = 0;
245 int err;
246 unsigned long ecode;
247
250 n = SSL_write(conn->ssl, ptr, len);
251 err = SSL_get_error(conn->ssl, n);
252 ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
253 switch (err)
254 {
255 case SSL_ERROR_NONE:
256 if (n < 0)
257 {
258 /* Not supposed to happen, so we don't translate the msg */
260 "SSL_write failed but did not provide error information\n");
261 /* assume the connection is broken */
263 }
264 break;
266
267 /*
268 * Returning 0 here causes caller to wait for write-ready, which
269 * is not really the right thing, but it's the best we can do.
270 */
271 n = 0;
272 break;
274 n = 0;
275 break;
277
278 /*
279 * If errno is still zero then assume it's a read EOF situation,
280 * and report EOF. (This seems possible because SSL_write can
281 * also do reads.)
282 */
283 if (n < 0 && SOCK_ERRNO != 0)
284 {
287 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
288 "\tThis probably means the server terminated abnormally\n"
289 "\tbefore or while processing the request.");
290 else
291 libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
293 sebuf, sizeof(sebuf)));
294 }
295 else
296 {
297 libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
298 /* assume the connection is broken */
300 n = -1;
301 }
302 break;
303 case SSL_ERROR_SSL:
304 {
305 char *errm = SSLerrmessage(ecode);
306
307 libpq_append_conn_error(conn, "SSL error: %s", errm);
309 /* assume the connection is broken */
311 n = -1;
312 break;
313 }
315
316 /*
317 * Per OpenSSL documentation, this error code is only returned for
318 * a clean connection closure, so we should not report it as a
319 * server crash.
320 */
321 libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
323 n = -1;
324 break;
325 default:
326 libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
327 /* assume the connection is broken */
329 n = -1;
330 break;
331 }
332
333 /* ensure we return the intended errno to caller */
335
336 return n;
337}

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

1906{
1907 if (conn && conn->sslpassword)
1908 {
1909 if (strlen(conn->sslpassword) + 1 > size)
1910 fprintf(stderr, libpq_gettext("WARNING: sslpassword truncated\n"));
1911 strncpy(buf, conn->sslpassword, size);
1912 buf[size - 1] = '\0';
1913 return strlen(buf);
1914 }
1915 else
1916 {
1917 buf[0] = '\0';
1918 return 0;
1919 }
1920}

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

Referenced by PQssl_passwd_cb().

◆ PQgetssl()

void * PQgetssl ( PGconn conn)

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

1628{
1629 if (!conn)
1630 return NULL;
1631 return conn->ssl;
1632}

References conn, and fb().

◆ PQgetSSLKeyPassHook_OpenSSL()

PQsslKeyPassHook_OpenSSL_type PQgetSSLKeyPassHook_OpenSSL ( void  )

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

1924{
1925 return PQsslKeyPassHook;
1926}

References PQsslKeyPassHook.

◆ PQsetSSLKeyPassHook_OpenSSL()

void PQsetSSLKeyPassHook_OpenSSL ( PQsslKeyPassHook_OpenSSL_type  hook)

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

1930{
1931 PQsslKeyPassHook = hook;
1932}

References PQsslKeyPassHook.

◆ PQssl_passwd_cb()

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

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

1941{
1942 PGconn *conn = userdata;
1943
1944 if (PQsslKeyPassHook)
1945 return PQsslKeyPassHook(buf, size, conn);
1946 else
1948}
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 1672 of file fe-secure-openssl.c.

1673{
1674 if (!conn)
1675 {
1676 /* PQsslAttribute(NULL, "library") reports the default SSL library */
1677 if (strcmp(attribute_name, "library") == 0)
1678 return "OpenSSL";
1679 return NULL;
1680 }
1681
1682 /* All attributes read as NULL for a non-encrypted connection */
1683 if (conn->ssl == NULL)
1684 return NULL;
1685
1686 if (strcmp(attribute_name, "library") == 0)
1687 return "OpenSSL";
1688
1689 if (strcmp(attribute_name, "key_bits") == 0)
1690 {
1691 static char sslbits_str[12];
1692 int sslbits;
1693
1695 snprintf(sslbits_str, sizeof(sslbits_str), "%d", sslbits);
1696 return sslbits_str;
1697 }
1698
1699 if (strcmp(attribute_name, "cipher") == 0)
1700 return SSL_get_cipher(conn->ssl);
1701
1702 if (strcmp(attribute_name, "compression") == 0)
1703 return SSL_get_current_compression(conn->ssl) ? "on" : "off";
1704
1705 if (strcmp(attribute_name, "protocol") == 0)
1706 return SSL_get_version(conn->ssl);
1707
1708 if (strcmp(attribute_name, "alpn") == 0)
1709 {
1710 const unsigned char *data;
1711 unsigned int len;
1712 static char alpn_str[256]; /* alpn doesn't support longer than 255
1713 * bytes */
1714
1716 if (data == NULL || len == 0 || len > sizeof(alpn_str) - 1)
1717 return "";
1719 alpn_str[len] = 0;
1720 return alpn_str;
1721 }
1722
1723 return NULL; /* unknown attribute */
1724}
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 1645 of file fe-secure-openssl.c.

1646{
1647 static const char *const openssl_attrs[] = {
1648 "library",
1649 "key_bits",
1650 "cipher",
1651 "compression",
1652 "protocol",
1653 "alpn",
1654 NULL
1655 };
1656 static const char *const empty_attrs[] = {NULL};
1657
1658 if (!conn)
1659 {
1660 /* Return attributes of default SSL library */
1661 return openssl_attrs;
1662 }
1663
1664 /* No attrs for unencrypted connection */
1665 if (conn->ssl == NULL)
1666 return empty_attrs;
1667
1668 return openssl_attrs;
1669}

References conn, and fb().

◆ PQsslStruct()

void * PQsslStruct ( PGconn conn,
const char struct_name 
)

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

1636{
1637 if (!conn)
1638 return NULL;
1639 if (strcmp(struct_name, "OpenSSL") == 0)
1640 return conn->ssl;
1641 return NULL;
1642}

References conn, and fb().

◆ ssl_protocol_version_to_openssl()

static int ssl_protocol_version_to_openssl ( const char protocol)
static

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

1962{
1963 if (pg_strcasecmp("TLSv1", protocol) == 0)
1964 return TLS1_VERSION;
1965
1966#ifdef TLS1_1_VERSION
1967 if (pg_strcasecmp("TLSv1.1", protocol) == 0)
1968 return TLS1_1_VERSION;
1969#endif
1970
1971#ifdef TLS1_2_VERSION
1972 if (pg_strcasecmp("TLSv1.2", protocol) == 0)
1973 return TLS1_2_VERSION;
1974#endif
1975
1976#ifdef TLS1_3_VERSION
1977 if (pg_strcasecmp("TLSv1.3", protocol) == 0)
1978 return TLS1_3_VERSION;
1979#endif
1980
1981 return -1;
1982}
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 1879 of file fe-secure-openssl.c.

1880{
1881 BIO *bio;
1883
1885 if (bio_method == NULL)
1886 return 0;
1887
1889 if (bio == NULL)
1890 return 0;
1891
1893 BIO_set_init(bio, 1);
1894
1895 SSL_set_bio(conn->ssl, bio, bio);
1896 return 1;
1897}
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 1613 of file fe-secure-openssl.c.

1614{
1615 if (buf != ssl_nomem)
1616 free(buf);
1617}
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 1555 of file fe-secure-openssl.c.

1556{
1557 const char *errreason;
1558 char *errbuf;
1559
1560 errbuf = malloc(SSL_ERR_LEN);
1561 if (!errbuf)
1562 return ssl_nomem;
1563 if (ecode == 0)
1564 {
1565 snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("no SSL error reported"));
1566 return errbuf;
1567 }
1568 errreason = ERR_reason_error_string(ecode);
1569 if (errreason != NULL)
1570 {
1571 strlcpy(errbuf, errreason, SSL_ERR_LEN);
1572 return errbuf;
1573 }
1574
1575 /*
1576 * Server aborted the connection with TLS "no_application_protocol" alert.
1577 * The ERR_reason_error_string() function doesn't give any error string
1578 * for that for some reason, so do it ourselves. See
1579 * https://github.com/openssl/openssl/issues/24300. This is available in
1580 * OpenSSL 1.1.0 and later, as well as in LibreSSL 3.4.3 (OpenBSD 7.0) and
1581 * later.
1582 */
1583#ifdef SSL_AD_NO_APPLICATION_PROTOCOL
1584 if (ERR_GET_LIB(ecode) == ERR_LIB_SSL &&
1586 {
1587 snprintf(errbuf, SSL_ERR_LEN, "no application protocol");
1588 return errbuf;
1589 }
1590#endif
1591
1592 /*
1593 * In OpenSSL 3.0.0 and later, ERR_reason_error_string does not map system
1594 * errno values anymore. (See OpenSSL source code for the explanation.)
1595 * We can cover that shortcoming with this bit of code. Older OpenSSL
1596 * versions don't have the ERR_SYSTEM_ERROR macro, but that's okay because
1597 * they don't have the shortcoming either.
1598 */
1599#ifdef ERR_SYSTEM_ERROR
1601 {
1603 return errbuf;
1604 }
1605#endif
1606
1607 /* No choice but to report the numeric ecode */
1608 snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("SSL error code %lu"), ecode);
1609 return errbuf;
1610}
#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 430 of file fe-secure-openssl.c.

431{
432 return ok;
433}

References fb().

Referenced by initialize_SSL().

Variable Documentation

◆ alpn_protos

unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR
static

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

Referenced by initialize_SSL().

◆ pgconn_bio_method_ptr

BIO_METHOD* pgconn_bio_method_ptr
static

Definition at line 1736 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 86 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 1550 of file fe-secure-openssl.c.

Referenced by SSLerrfree(), and SSLerrmessage().