PostgreSQL Source Code: src/interfaces/libpq/fe-secure-openssl.c File Reference (original) (raw)
739{
745 bool have_homedir;
746 bool have_cert;
747 bool have_rootcert;
748
749
750
751
752
753
760 else
761 have_homedir = false;
762
763
764
765
766
767
768
769
770 SSL_context = SSL_CTX_new(SSLv23_method());
772 {
774
777 return -1;
778 }
779
780
781
782
783
784
785
786
787
788
789
790
791
794 {
796 SSL_CTX_set_default_passwd_cb_userdata(SSL_context, conn);
797 }
798
799#ifdef HAVE_SSL_CTX_SET_CERT_CB
800
802#endif
803
804
805 SSL_CTX_set_options(SSL_context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
806
807
810 {
811 int ssl_min_ver;
812
814
815 if (ssl_min_ver == -1)
816 {
820 return -1;
821 }
822
823 if (!SSL_CTX_set_min_proto_version(SSL_context, ssl_min_ver))
824 {
826
830 return -1;
831 }
832 }
833
836 {
837 int ssl_max_ver;
838
840
841 if (ssl_max_ver == -1)
842 {
846 return -1;
847 }
848
849 if (!SSL_CTX_set_max_proto_version(SSL_context, ssl_max_ver))
850 {
852
856 return -1;
857 }
858 }
859
860
861
862
863
864 SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
865
866
867
868
869
870
873 else if (have_homedir)
874 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
875 else
876 fnbuf[0] = '\0';
877
878 if (strcmp(fnbuf, "system") == 0)
879 {
880
881
882
883
884
885
886
887 if (SSL_CTX_set_default_verify_paths(SSL_context) != 1)
888 {
890
895 return -1;
896 }
897 have_rootcert = true;
898 }
899 else if (fnbuf[0] != '\0' &&
901 {
902 X509_STORE *cvstore;
903
904 if (SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL) != 1)
905 {
907
909 fnbuf, err);
912 return -1;
913 }
914
915 if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
916 {
917 char *fname = NULL;
918 char *dname = NULL;
919
924
925
926 if (!fname && !dname && have_homedir)
927 {
928 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE);
929 fname = fnbuf;
930 }
931
932
933 if ((fname || dname) &&
934 X509_STORE_load_locations(cvstore, fname, dname) == 1)
935 {
936 X509_STORE_set_flags(cvstore,
937 X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
938 }
939
940
941 ERR_clear_error();
942 }
943 have_rootcert = true;
944 }
945 else
946 {
947
948
949
950
951
952 if (conn->sslmode[0] == 'v')
953 {
954
955
956
957
958
959 if (fnbuf[0] == '\0')
961 "Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification.");
962 else
964 "Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification.", fnbuf);
966 return -1;
967 }
968 have_rootcert = false;
969 }
970
971
974 else if (have_homedir)
975 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
976 else
977 fnbuf[0] = '\0';
978
980 {
981
982 have_cert = false;
983 }
984 else if (fnbuf[0] == '\0')
985 {
986
987 have_cert = false;
988 }
989 else if (stat(fnbuf, &buf) != 0)
990 {
991
992
993
994
995
996 if (errno != ENOENT && errno != ENOTDIR)
997 {
999 fnbuf, strerror_r(errno, sebuf, sizeof(sebuf)));
1001 return -1;
1002 }
1003 have_cert = false;
1004 }
1005 else
1006 {
1007
1008
1009
1010
1011
1012 if (SSL_CTX_use_certificate_chain_file(SSL_context, fnbuf) != 1)
1013 {
1015
1017 fnbuf, err);
1020 return -1;
1021 }
1022
1023
1024 have_cert = true;
1025 }
1026
1027
1028
1029
1030
1031
1032
1033
1035 !SSL_set_app_data(conn->ssl, conn) ||
1037 {
1039
1043 return -1;
1044 }
1046
1048 {
1049#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK
1050 SSL_CTX_set_keylog_callback(SSL_context, SSL_CTX_keylog_cb);
1051#else
1052#ifdef LIBRESSL_VERSION_NUMBER
1053 fprintf(stderr, libpq_gettext("WARNING: sslkeylogfile support requires OpenSSL\n"));
1054#else
1055 fprintf(stderr, libpq_gettext("WARNING: libpq was not built with sslkeylogfile support\n"));
1056#endif
1057#endif
1058 }
1059
1060
1061
1062
1063
1064
1065
1068
1069
1070
1071
1072
1073
1075 {
1077
1078 if (host && host[0] &&
1079 !(strspn(host, "0123456789.") == strlen(host) ||
1080 strchr(host, ':')))
1081 {
1082 if (SSL_set_tlsext_host_name(conn->ssl, host) != 1)
1083 {
1085
1088 return -1;
1089 }
1090 }
1091 }
1092
1093
1094 {
1095 int retval;
1096
1098
1099 if (retval != 0)
1100 {
1102
1105 return -1;
1106 }
1107 }
1108
1109
1110
1111
1112
1113
1114
1116 {
1117#ifdef USE_SSL_ENGINE
1119#ifdef WIN32
1121#endif
1122 )
1123 {
1124
1125 char *engine_str = strdup(conn->sslkey);
1126 char *engine_colon;
1127 EVP_PKEY *pkey;
1128
1129 if (engine_str == NULL)
1130 {
1132 return -1;
1133 }
1134
1135
1136 engine_colon = strchr(engine_str, ':');
1137
1138 *engine_colon = '\0';
1139 engine_colon++;
1140
1141 conn->engine = ENGINE_by_id(engine_str);
1142 if (conn->engine == NULL)
1143 {
1145
1147 engine_str, err);
1149 free(engine_str);
1150 return -1;
1151 }
1152
1153 if (ENGINE_init(conn->engine) == 0)
1154 {
1156
1158 engine_str, err);
1160 ENGINE_free(conn->engine);
1161 conn->engine = NULL;
1162 free(engine_str);
1163 return -1;
1164 }
1165
1166 pkey = ENGINE_load_private_key(conn->engine, engine_colon,
1167 NULL, NULL);
1168 if (pkey == NULL)
1169 {
1171
1173 engine_colon, engine_str, err);
1175 ENGINE_finish(conn->engine);
1176 ENGINE_free(conn->engine);
1177 conn->engine = NULL;
1178 free(engine_str);
1179 return -1;
1180 }
1181 if (SSL_use_PrivateKey(conn->ssl, pkey) != 1)
1182 {
1184
1186 engine_colon, engine_str, err);
1188 ENGINE_finish(conn->engine);
1189 ENGINE_free(conn->engine);
1190 conn->engine = NULL;
1191 free(engine_str);
1192 return -1;
1193 }
1194
1195 free(engine_str);
1196
1197 fnbuf[0] = '\0';
1198
1199 }
1200 else
1201#endif
1202 {
1203
1205 }
1206 }
1207 else if (have_homedir)
1208 {
1209
1210 snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
1211 }
1212 else
1213 fnbuf[0] = '\0';
1214
1215 if (have_cert && fnbuf[0] != '\0')
1216 {
1217
1218
1219 if (stat(fnbuf, &buf) != 0)
1220 {
1221 if (errno == ENOENT)
1223 fnbuf);
1224 else
1226 fnbuf);
1227 return -1;
1228 }
1229
1230
1232 {
1234 fnbuf);
1235 return -1;
1236 }
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260#if !defined(WIN32) && !defined(__CYGWIN__)
1261 if (buf.st_uid == 0 ?
1264 {
1266 "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",
1267 fnbuf);
1268 return -1;
1269 }
1270#endif
1271
1272 if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_PEM) != 1)
1273 {
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288 if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_ASN1) != 1)
1289 {
1291 fnbuf, err);
1293 return -1;
1294 }
1295
1297 }
1298 }
1299
1300
1301 if (have_cert &&
1302 SSL_check_private_key(conn->ssl) != 1)
1303 {
1305
1307 fnbuf, err);
1309 return -1;
1310 }
1311
1312
1313
1314
1315
1316 if (have_rootcert)
1317 SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, verify_cb);
1318
1319
1320
1321
1323 SSL_set_options(conn->ssl, SSL_OP_NO_COMPRESSION);
1324 else
1325 SSL_clear_options(conn->ssl, SSL_OP_NO_COMPRESSION);
1326
1327 return 0;
1328}
static SSL_CTX * SSL_context
#define fprintf(file, fmt, msg)
void err(int eval, const char *fmt,...)
bool pqGetHomeDirectory(char *buf, int bufsize)
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)
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
#define PG_STRERROR_R_BUFLEN
size_t strlcpy(char *dst, const char *src, size_t siz)
char * ssl_max_protocol_version
char * ssl_min_protocol_version