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