END;
$d$;
ERROR: invalid option "password"
-HINT: Valid options in this context are: service, passfile, channel_binding, connect_timeout, dbname, host, hostaddr, port, options, application_name, keepalives, keepalives_idle, keepalives_interval, keepalives_count, tcp_user_timeout, sslmode, sslcompression, sslcert, sslkey, sslrootcert, sslcrl, requirepeer, ssl_min_protocol_version, ssl_max_protocol_version, gssencmode, krbsrvname, gsslib, target_session_attrs, use_remote_estimate, fdw_startup_cost, fdw_tuple_cost, extensions, updatable, fetch_size, batch_size
+HINT: Valid options in this context are: service, passfile, channel_binding, connect_timeout, dbname, host, hostaddr, port, options, application_name, keepalives, keepalives_idle, keepalives_interval, keepalives_count, tcp_user_timeout, sslmode, sslcompression, sslcert, sslkey, sslrootcert, sslcrl, sslcrldir, requirepeer, ssl_min_protocol_version, ssl_max_protocol_version, gssencmode, krbsrvname, gsslib, target_session_attrs, use_remote_estimate, fdw_startup_cost, fdw_tuple_cost, extensions, updatable, fetch_size, batch_size
CONTEXT: SQL statement "ALTER SERVER loopback_nopw OPTIONS (ADD password 'dummypw')"
PL/pgSQL function inline_code_block line 3 at EXECUTE
-- If we add a password for our user mapping instead, we should get a different
Relative paths are relative to the data directory.
This parameter can only be set in the postgresql.conf
file or on the server command line.
- The default is empty, meaning no CRL file is loaded.
+ The default is empty, meaning no CRL file is loaded (unless
+ is set).
+
+
+
+
+
+ ssl_crl_dir (string)
+
+
ssl_crl_dir configuration parameter
+
+
+
+ Specifies the name of the directory containing the SSL server
+ certificate revocation list (CRL). Relative paths are relative to the
+ data directory. This parameter can only be set in
+ the postgresql.conf file or on the server command
+ line. The default is empty, meaning no CRLs are used (unless
+ is set).
+
+
+ The directory needs to be prepared with the OpenSSL command
+ openssl rehash or c_rehash. See
+ its documentation for details.
+
+
+ When using this setting, CRLs in the specified directory are loaded
+ on-demand at connection time. New CRLs can be added to the directory
+ and will be used immediately. This is unlike
+ linkend="guc-ssl-crl-file"/>, which causes the CRL in the file to be
+ loaded at server start time or when the configuration is reloaded.
+ Both settings can be used together.
This parameter specifies the file name of the SSL certificate
revocation list (CRL). Certificates listed in this file, if it
exists, will be rejected while attempting to authenticate the
- server's certificate. The default is
+ server's certificate. If neither
+ nor
+ is set, this setting is
+ taken as
~/.postgresql/root.crl.
+
+ sslcrldir
+
+ This parameter specifies the directory name of the SSL certificate
+ revocation list (CRL). Certificates listed in the files in this
+ directory, if it exists, will be rejected while attempting to
+ authenticate the server's certificate.
+
+
+ The directory needs to be prepared with the OpenSSL command
+ openssl rehash or c_rehash. See
+ its documentation for details.
+
+
+ Both sslcrl and sslcrldir can be
+ specified together.
+
+
+
+
requirepeer
* http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html
*----------
*/
- if (ssl_crl_file[0])
+ if (ssl_crl_file[0] || ssl_crl_dir[0])
{
X509_STORE *cvstore = SSL_CTX_get_cert_store(context);
if (cvstore)
{
/* Set the flags to check against the complete CRL chain */
- if (X509_STORE_load_locations(cvstore, ssl_crl_file, NULL) == 1)
+ if (X509_STORE_load_locations(cvstore,
+ ssl_crl_file[0] ? ssl_crl_file : NULL,
+ ssl_crl_dir[0] ? ssl_crl_dir : NULL)
+ == 1)
{
X509_STORE_set_flags(cvstore,
X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
}
- else
+ else if (ssl_crl_dir[0] == 0)
{
ereport(isServerStart ? FATAL : LOG,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
ssl_crl_file, SSLerrmessage(ERR_get_error()))));
goto error;
}
+ else if (ssl_crl_file[0] == 0)
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("could not load SSL certificate revocation list directory \"%s\": %s",
+ ssl_crl_dir, SSLerrmessage(ERR_get_error()))));
+ goto error;
+ }
+ else
+ {
+ ereport(isServerStart ? FATAL : LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("could not load SSL certificate revocation list file \"%s\" or directory \"%s\": %s",
+ ssl_crl_file, ssl_crl_dir,
+ SSLerrmessage(ERR_get_error()))));
+ goto error;
+ }
}
}
char *ssl_key_file;
char *ssl_ca_file;
char *ssl_crl_file;
+char *ssl_crl_dir;
char *ssl_dh_params_file;
char *ssl_passphrase_command;
bool ssl_passphrase_command_supports_reload;
NULL, NULL, NULL
},
+ {
+ {"ssl_crl_dir", PGC_SIGHUP, CONN_AUTH_SSL,
+ gettext_noop("Location of the SSL certificate revocation list directory."),
+ NULL
+ },
+ &ssl_crl_dir,
+ "",
+ NULL, NULL, NULL
+ },
+
{
{"stats_temp_directory", PGC_SIGHUP, STATS_COLLECTOR,
gettext_noop("Writes temporary statistics files to the specified directory."),
#ssl_ca_file = ''
#ssl_cert_file = 'server.crt'
#ssl_crl_file = ''
+#ssl_crl_dir = ''
#ssl_key_file = 'server.key'
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers
#ssl_prefer_server_ciphers = on
extern char *ssl_key_file;
extern char *ssl_ca_file;
extern char *ssl_crl_file;
+extern char *ssl_crl_dir;
extern char *ssl_dh_params_file;
extern PGDLLIMPORT char *ssl_passphrase_command;
extern PGDLLIMPORT bool ssl_passphrase_command_supports_reload;
"SSL-Revocation-List", "", 64,
offsetof(struct pg_conn, sslcrl)},
+ {"sslcrldir", "PGSSLCRLDIR", NULL, NULL,
+ "SSL-Revocation-List-Dir", "", 64,
+ offsetof(struct pg_conn, sslcrldir)},
+
{"requirepeer", "PGREQUIREPEER", NULL, NULL,
"Require-Peer", "", 10,
offsetof(struct pg_conn, requirepeer)},
free(conn->sslrootcert);
if (conn->sslcrl)
free(conn->sslcrl);
+ if (conn->sslcrldir)
+ free(conn->sslcrldir);
if (conn->sslcompression)
free(conn->sslcompression);
if (conn->requirepeer)
if (!(conn->sslcert && strlen(conn->sslcert) > 0) ||
!(conn->sslkey && strlen(conn->sslkey) > 0) ||
!(conn->sslrootcert && strlen(conn->sslrootcert) > 0) ||
- !(conn->sslcrl && strlen(conn->sslcrl) > 0))
+ !((conn->sslcrl && strlen(conn->sslcrl) > 0) ||
+ (conn->sslcrldir && strlen(conn->sslcrldir) > 0)))
have_homedir = pqGetHomeDirectory(homedir, sizeof(homedir));
else /* won't need it */
have_homedir = false;
if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
{
+ char *fname = NULL;
+ char *dname = NULL;
+
if (conn->sslcrl && strlen(conn->sslcrl) > 0)
- strlcpy(fnbuf, conn->sslcrl, sizeof(fnbuf));
- else if (have_homedir)
+ fname = conn->sslcrl;
+ if (conn->sslcrldir && strlen(conn->sslcrldir) > 0)
+ dname = conn->sslcrldir;
+
+ /* defaults to use the default CRL file */
+ if (!fname && !dname && have_homedir)
+ {
snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE);
- else
- fnbuf[0] = '\0';
+ fname = fnbuf;
+ }
/* Set the flags to check against the complete CRL chain */
- if (fnbuf[0] != '\0' &&
- X509_STORE_load_locations(cvstore, fnbuf, NULL) == 1)
+ if ((fname || dname) &&
+ X509_STORE_load_locations(cvstore, fname, dname) == 1)
{
X509_STORE_set_flags(cvstore,
X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
}
+
/* if not found, silently ignore; we do not require CRL */
ERR_clear_error();
}
char *sslpassword; /* client key file password */
char *sslrootcert; /* root certificate filename */
char *sslcrl; /* certificate revocation list filename */
+ char *sslcrldir; /* certificate revocation list directory name */
char *requirepeer; /* required peer credentials for local sockets */
char *gssencmode; /* GSS mode (require,prefer,disable) */
char *krbsrvname; /* Kerberos service name */
ssl/client+client_ca.crt ssl/client-der.key \
ssl/client-encrypted-pem.key ssl/client-encrypted-der.key
+SSLDIRS := ssl/client-crldir ssl/server-crldir \
+ ssl/root+client-crldir ssl/root+server-crldir
+
# This target re-generates all the key and certificate files. Usually we just
# use the ones that are committed to the tree without rebuilding them.
#
# This target will fail unless preceded by sslfiles-clean.
#
-sslfiles: $(SSLFILES)
+sslfiles: $(SSLFILES) $(SSLDIRS)
# OpenSSL requires a directory to put all generated certificates in. We don't
# use this for anything, but we need a location.
ssl/root+client.crl: ssl/root.crl ssl/client.crl
cat $^ > $@
+ssl/root+server-crldir: ssl/server.crl ssl/root.crl
+ mkdir ssl/root+server-crldir
+ cp ssl/server.crl ssl/root+server-crldir/`openssl crl -hash -noout -in ssl/server.crl`.r0
+ cp ssl/root.crl ssl/root+server-crldir/`openssl crl -hash -noout -in ssl/root.crl`.r0
+
+ssl/root+client-crldir: ssl/client.crl ssl/root.crl
+ mkdir ssl/root+client-crldir
+ cp ssl/client.crl ssl/root+client-crldir/`openssl crl -hash -noout -in ssl/client.crl`.r0
+ cp ssl/root.crl ssl/root+client-crldir/`openssl crl -hash -noout -in ssl/root.crl`.r0
+
+ssl/server-crldir: ssl/server.crl
+ mkdir ssl/server-crldir
+ cp ssl/server.crl ssl/server-crldir/`openssl crl -hash -noout -in ssl/server.crl`.r0
+
+ssl/client-crldir: ssl/client.crl
+ mkdir ssl/client-crldir
+ cp ssl/client.crl ssl/client-crldir/`openssl crl -hash -noout -in ssl/client.crl`.r0
+
.PHONY: sslfiles-clean
sslfiles-clean:
rm -f $(SSLFILES) ssl/client_ca.srl ssl/server_ca.srl ssl/client_ca-certindex* ssl/server_ca-certindex* ssl/root_ca-certindex* ssl/root_ca.srl ssl/temp_ca.crt ssl/temp_ca_signed.crt
+ rm -rf $(SSLDIRS)
clean distclean maintainer-clean:
rm -rf tmp_check
--- /dev/null
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3QgY2xpZW50IGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBAhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAXjLxA9Qc6gAudwUHBxMIq5EHBcuNEX5e3GNlkyNf
+8I0DtHTPfJPvmAG+i6lYz//hHmmjxK0dR2ucg79XgXI/6OpDqlxS/TG1Xv52wA1p
+xz6GaJ2hC8Lk4/vbJo/Rrzme2QsI7xqBWya0JWVrehttqhFxPzWA5wID8X7G4Kb4
+pjVnzqYzn8A9FBiV9t10oZg60aVLqt3kbyy+U3pefvjhj8NmQc7uyuVjWvYZA0vG
+nnDUo4EKJzHNIYLk+EfpzKWO2XAWBLOT9SyyNCeMuQ5p/2pdAt9jtWHenms2ajo9
+2iUsHS91e3TooP9yNYuNcN8/wXY6H2Xm+dCLcEnkcr7EEw==
+-----END X509 CRL-----
--- /dev/null
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3QgY2xpZW50IGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBAhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAXjLxA9Qc6gAudwUHBxMIq5EHBcuNEX5e3GNlkyNf
+8I0DtHTPfJPvmAG+i6lYz//hHmmjxK0dR2ucg79XgXI/6OpDqlxS/TG1Xv52wA1p
+xz6GaJ2hC8Lk4/vbJo/Rrzme2QsI7xqBWya0JWVrehttqhFxPzWA5wID8X7G4Kb4
+pjVnzqYzn8A9FBiV9t10oZg60aVLqt3kbyy+U3pefvjhj8NmQc7uyuVjWvYZA0vG
+nnDUo4EKJzHNIYLk+EfpzKWO2XAWBLOT9SyyNCeMuQ5p/2pdAt9jtWHenms2ajo9
+2iUsHS91e3TooP9yNYuNcN8/wXY6H2Xm+dCLcEnkcr7EEw==
+-----END X509 CRL-----
--- /dev/null
+-----BEGIN X509 CRL-----
+MIIBhTBvMA0GCSqGSIb3DQEBCwUAMEAxPjA8BgNVBAMMNVRlc3Qgcm9vdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHN1aXRlFw0xODExMjcx
+MzQwNTVaFw00NjA0MTQxMzQwNTVaMA0GCSqGSIb3DQEBCwUAA4IBAQB8OSDym4/a
+qbZOrZvOOhmKrd7AJSTgAadtdK0CX3v58Ym3EmZK7gQFdBuFCXnvbue/x6avZHgz
+4pYFlJmL0IiD4QuTzsoo+LzifrmTzteO9oEJNLd2bjfEnpE5Wdaw6Yuy2Xb5edy5
+lQhNZdc8w3FiXhPOEUAi7EbdfDwn4G/fvEjpzyVb2wCujDUUePUGGayjKIM4PUu4
+pixM6gt9FFL27l47lQ3g0PbvB3TnU3oqcB3Y17FjbxjFc6AsGXholNetoEE2/49E
+PEYzOH7/PtxlZUtoCqZM+741LuI6Q7z4/P2X/IY33lMy6Iiyc41C94l/P7fCkMLG
+AlO+O0a4SpYS
+-----END X509 CRL-----
--- /dev/null
+-----BEGIN X509 CRL-----
+MIIBhTBvMA0GCSqGSIb3DQEBCwUAMEAxPjA8BgNVBAMMNVRlc3Qgcm9vdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHN1aXRlFw0xODExMjcx
+MzQwNTVaFw00NjA0MTQxMzQwNTVaMA0GCSqGSIb3DQEBCwUAA4IBAQB8OSDym4/a
+qbZOrZvOOhmKrd7AJSTgAadtdK0CX3v58Ym3EmZK7gQFdBuFCXnvbue/x6avZHgz
+4pYFlJmL0IiD4QuTzsoo+LzifrmTzteO9oEJNLd2bjfEnpE5Wdaw6Yuy2Xb5edy5
+lQhNZdc8w3FiXhPOEUAi7EbdfDwn4G/fvEjpzyVb2wCujDUUePUGGayjKIM4PUu4
+pixM6gt9FFL27l47lQ3g0PbvB3TnU3oqcB3Y17FjbxjFc6AsGXholNetoEE2/49E
+PEYzOH7/PtxlZUtoCqZM+741LuI6Q7z4/P2X/IY33lMy6Iiyc41C94l/P7fCkMLG
+AlO+O0a4SpYS
+-----END X509 CRL-----
--- /dev/null
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3Qgc2VydmVyIGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBBhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAbVuJXemxM6HLlIHGWlQvVmsmG4ZTQWiDnZjfmrND
+xB4XsvZNPXnFkjdBENDROrbDRwm60SJDW73AbDbfq1IXAzSpuEyuRz61IyYKo0wq
+nmObJtVdIu3bVlWIlDXaP5Emk3d7ouCj5f8Kyeb8gm4pL3N6e0eI63hCaS39hhE6
+RLGh9HU9ht1kKfgcTwmB5b2HTPb4M6z1AmSIaMVqZTjIspsUgNF2+GBm3fOnOaiZ
+SEXWtgjMRXiIHbtU0va3LhSH5OSW0mh+L9oGUQDYnyuudnWGpulhqIp4qVkJRDDu
+41HpD83dV2uRtBLvc25AFHj7kXBflbO3gvGZVPYf1zVghQ==
+-----END X509 CRL-----
--- /dev/null
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3Qgc2VydmVyIGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBBhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAbVuJXemxM6HLlIHGWlQvVmsmG4ZTQWiDnZjfmrND
+xB4XsvZNPXnFkjdBENDROrbDRwm60SJDW73AbDbfq1IXAzSpuEyuRz61IyYKo0wq
+nmObJtVdIu3bVlWIlDXaP5Emk3d7ouCj5f8Kyeb8gm4pL3N6e0eI63hCaS39hhE6
+RLGh9HU9ht1kKfgcTwmB5b2HTPb4M6z1AmSIaMVqZTjIspsUgNF2+GBm3fOnOaiZ
+SEXWtgjMRXiIHbtU0va3LhSH5OSW0mh+L9oGUQDYnyuudnWGpulhqIp4qVkJRDDu
+41HpD83dV2uRtBLvc25AFHj7kXBflbO3gvGZVPYf1zVghQ==
+-----END X509 CRL-----
}
else
{
- plan tests => 93;
+ plan tests => 100;
}
#### Some configuration
qr/SSL error/,
"CRL belonging to a different CA");
+# The same for CRL directory
+test_connect_fails(
+ $common_connstr,
+ "sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/client-crldir",
+ qr/SSL error/,
+ "directory CRL belonging to a different CA");
+
# With the correct CRL, succeeds (this cert is not revoked)
test_connect_ok(
$common_connstr,
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl",
"CRL with a non-revoked cert");
+# The same for CRL directory
+test_connect_ok(
+ $common_connstr,
+ "sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/root+server-crldir",
+ "directory CRL with a non-revoked cert");
+
# Check that connecting with verify-full fails, when the hostname doesn't
# match the hostname in the server's certificate.
$common_connstr =
$common_connstr,
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl",
qr/SSL error/,
- "does not connect with client-side CRL");
+ "does not connect with client-side CRL file");
+test_connect_fails(
+ $common_connstr,
+ "sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/root+server-crldir",
+ qr/SSL error/,
+ "does not connect with client-side CRL directory");
# pg_stat_ssl
command_like(
test_connect_fails($common_connstr, "sslmode=require sslcert=ssl/client.crt",
qr/SSL error/, "intermediate client certificate is missing");
+# test server-side CRL directory
+switch_server_cert($node, 'server-cn-only', undef, undef, 'root+client-crldir');
+
+# revoked client cert
+test_connect_fails(
+ $common_connstr,
+ "user=ssltestuser sslcert=ssl/client-revoked.crt sslkey=ssl/client-revoked_tmp.key",
+ qr/SSL error/,
+ "certificate authorization fails with revoked client cert with server-side CRL directory");
+
# clean up
foreach my $key (@keys)
{
copy_files("ssl/root+client_ca.crt", $pgdata);
copy_files("ssl/root_ca.crt", $pgdata);
copy_files("ssl/root+client.crl", $pgdata);
+ mkdir("$pgdata/root+client-crldir");
+ copy_files("ssl/root+client-crldir/*", "$pgdata/root+client-crldir/");
# Stop and restart server to load new listen_addresses.
$node->restart;
my $node = $_[0];
my $certfile = $_[1];
my $cafile = $_[2] || "root+client_ca";
+ my $crlfile = "root+client.crl";
+ my $crldir;
my $pgdata = $node->data_dir;
+ # defaults to use crl file
+ if (defined $_[3] || defined $_[4])
+ {
+ $crlfile = $_[3];
+ $crldir = $_[4];
+ }
+
open my $sslconf, '>', "$pgdata/sslconfig.conf";
print $sslconf "ssl=on\n";
print $sslconf "ssl_ca_file='$cafile.crt'\n";
print $sslconf "ssl_cert_file='$certfile.crt'\n";
print $sslconf "ssl_key_file='$certfile.key'\n";
- print $sslconf "ssl_crl_file='root+client.crl'\n";
+ print $sslconf "ssl_crl_file='$crlfile'\n" if defined $crlfile;
+ print $sslconf "ssl_crl_dir='$crldir'\n" if defined $crldir;
close $sslconf;
$node->restart;