Allow specifying CRL directory
authorPeter Eisentraut <[email protected]>
Thu, 18 Feb 2021 06:59:10 +0000 (07:59 +0100)
committerPeter Eisentraut <[email protected]>
Thu, 18 Feb 2021 06:59:10 +0000 (07:59 +0100)
Add another method to specify CRLs, hashed directory method, for both
server and client side.  This offers a means for server or libpq to
load only CRLs that are required to verify a certificate.  The CRL
directory is specifed by separate GUC variables or connection options
ssl_crl_dir and sslcrldir, alongside the existing ssl_crl_file and
sslcrl, so both methods can be used at the same time.

Author: Kyotaro Horiguchi <[email protected]>
Discussion: https://www.postgresql.org/message-id/flat/20200731.173911.904649928639357911[email protected]

20 files changed:
contrib/postgres_fdw/expected/postgres_fdw.out
doc/src/sgml/config.sgml
doc/src/sgml/libpq.sgml
src/backend/libpq/be-secure-openssl.c
src/backend/libpq/be-secure.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/include/libpq/libpq.h
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/fe-secure-openssl.c
src/interfaces/libpq/libpq-int.h
src/test/ssl/Makefile
src/test/ssl/ssl/client-crldir/9bb9e3c3.r0 [new file with mode: 0644]
src/test/ssl/ssl/root+client-crldir/9bb9e3c3.r0 [new file with mode: 0644]
src/test/ssl/ssl/root+client-crldir/a3d11bff.r0 [new file with mode: 0644]
src/test/ssl/ssl/root+server-crldir/a3d11bff.r0 [new file with mode: 0644]
src/test/ssl/ssl/root+server-crldir/a836cc2d.r0 [new file with mode: 0644]
src/test/ssl/ssl/server-crldir/a836cc2d.r0 [new file with mode: 0644]
src/test/ssl/t/001_ssltests.pl
src/test/ssl/t/SSLServer.pm

index 3326f1b542affdc25186d08a7bdd0d145fad3d2b..0649b6b81cd926f0e8158f55eca7616cb48ba93a 100644 (file)
@@ -8946,7 +8946,7 @@ DO $d$
     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
index 4df1405d2e2119c1f937c76234a4928f97ecf6be..e81141e45cf7a6f7bd66651f2199eb06dbe00ba9 100644 (file)
@@ -1216,7 +1216,41 @@ include_dir 'conf.d'
         Relative paths are relative to the data directory.
         This parameter can only be set in the <filename>postgresql.conf</filename>
         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
+        <xref linkend="guc-ssl-crl-dir"/> is set).
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry id="guc-ssl-crl-dir" xreflabel="ssl_crl_dir">
+      <term><varname>ssl_crl_dir</varname> (<type>string</type>)
+      <indexterm>
+       <primary><varname>ssl_crl_dir</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        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 <filename>postgresql.conf</filename> file or on the server command
+        line.  The default is empty, meaning no CRLs are used (unless
+        <xref linkend="guc-ssl-crl-file"/> is set).
+       </para>
+
+       <para>
+        The directory needs to be prepared with the OpenSSL command
+        <literal>openssl rehash</literal> or <literal>c_rehash</literal>.  See
+        its documentation for details.
+       </para>
+
+       <para>
+        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 <xref
+        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.
        </para>
       </listitem>
      </varlistentry>
index b7a82453f0da16437be711ce331f24cc42c78381..5e25f20843c1110bce65dd872a9751ef17f70975 100644 (file)
@@ -1723,12 +1723,38 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
         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
+        <xref linkend='libpq-connect-sslcrl'/> nor
+        <xref linkend='libpq-connect-sslcrldir'/> is set, this setting is
+        taken as
         <filename>~/.postgresql/root.crl</filename>.
        </para>
       </listitem>
      </varlistentry>
 
+     <varlistentry id="libpq-connect-sslcrldir" xreflabel="sslcrldir">
+      <term><literal>sslcrldir</literal></term>
+      <listitem>
+       <para>
+        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.
+       </para>
+
+       <para>
+        The directory needs to be prepared with the OpenSSL command
+        <literal>openssl rehash</literal> or <literal>c_rehash</literal>.  See
+        its documentation for details.
+       </para>
+
+       <para>
+        Both <literal>sslcrl</literal> and <literal>sslcrldir</literal> can be
+        specified together.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="libpq-connect-requirepeer" xreflabel="requirepeer">
       <term><literal>requirepeer</literal></term>
       <listitem>
index 1e2ecc6e7ab7411a6178d2c331c39de2f80f6779..4c4f025eb1a76dc428d15fec9f47be380df2cf7f 100644 (file)
@@ -285,19 +285,22 @@ be_tls_init(bool isServerStart)
     * 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),
@@ -305,6 +308,23 @@ be_tls_init(bool isServerStart)
                                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;
+           }
        }
    }
 
index 7155b3388524504c875f117358e5f79c9113caf8..d1545a2ad6ade3f75240df0583a0e5152cc15c2d 100644 (file)
@@ -42,6 +42,7 @@ char     *ssl_cert_file;
 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;
index eafdb1118ed57b746892d0478b0f5b0b268b93bd..00018abb7d1f22bf7ca2312cef99bca8a25dc122 100644 (file)
@@ -4355,6 +4355,16 @@ static struct config_string ConfigureNamesString[] =
        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."),
index db6db376eb055b0fe20ee8453e9932eb8c692f30..ee06528bb0b91f175d0a9a55502fa078768ee91e 100644 (file)
 #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
index a55898c85afe1e013c94035e5d246198f90a5046..b41b10620aae9766407060f8173a2948c58dd9cc 100644 (file)
@@ -82,6 +82,7 @@ extern char *ssl_cert_file;
 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;
index 8ca0583aa908ddd09ce2ebb19d87996bd587789b..db71fea169c96f1d417f843ee2ef9928efe4ceef 100644 (file)
@@ -317,6 +317,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
        "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)},
@@ -3998,6 +4002,8 @@ freePGconn(PGconn *conn)
        free(conn->sslrootcert);
    if (conn->sslcrl)
        free(conn->sslcrl);
+   if (conn->sslcrldir)
+       free(conn->sslcrldir);
    if (conn->sslcompression)
        free(conn->sslcompression);
    if (conn->requirepeer)
index 5b4a4157d5ce8560dfa2987437391f5fc3a990ea..0fa10a23b4a5d652913c51ec3fed32c34a988e1e 100644 (file)
@@ -794,7 +794,8 @@ initialize_SSL(PGconn *conn)
    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;
@@ -936,20 +937,29 @@ initialize_SSL(PGconn *conn)
 
        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();
        }
index 4db498369c7bef9c9e3113d433689003a670d14a..ce36aabd25a9262e18314dc9a780a603626d0a66 100644 (file)
@@ -362,6 +362,7 @@ struct pg_conn
    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 */
index d545382eea2a4862c1524a12590fe08efb7c39fc..4b53fdf6c0d3d16aa7f3ea1d42813c7feb8a2981 100644 (file)
@@ -30,12 +30,15 @@ SSLFILES := $(CERTIFICATES:%=ssl/%.key) $(CERTIFICATES:%=ssl/%.crt) \
    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.
@@ -147,9 +150,28 @@ ssl/root+server.crl: ssl/root.crl ssl/server.crl
 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
diff --git a/src/test/ssl/ssl/client-crldir/9bb9e3c3.r0 b/src/test/ssl/ssl/client-crldir/9bb9e3c3.r0
new file mode 100644 (file)
index 0000000..a667680
--- /dev/null
@@ -0,0 +1,11 @@
+-----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-----
diff --git a/src/test/ssl/ssl/root+client-crldir/9bb9e3c3.r0 b/src/test/ssl/ssl/root+client-crldir/9bb9e3c3.r0
new file mode 100644 (file)
index 0000000..a667680
--- /dev/null
@@ -0,0 +1,11 @@
+-----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-----
diff --git a/src/test/ssl/ssl/root+client-crldir/a3d11bff.r0 b/src/test/ssl/ssl/root+client-crldir/a3d11bff.r0
new file mode 100644 (file)
index 0000000..e879cf2
--- /dev/null
@@ -0,0 +1,11 @@
+-----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-----
diff --git a/src/test/ssl/ssl/root+server-crldir/a3d11bff.r0 b/src/test/ssl/ssl/root+server-crldir/a3d11bff.r0
new file mode 100644 (file)
index 0000000..e879cf2
--- /dev/null
@@ -0,0 +1,11 @@
+-----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-----
diff --git a/src/test/ssl/ssl/root+server-crldir/a836cc2d.r0 b/src/test/ssl/ssl/root+server-crldir/a836cc2d.r0
new file mode 100644 (file)
index 0000000..717951c
--- /dev/null
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3Qgc2VydmVyIGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBBhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAbVuJXemxM6HLlIHGWlQvVmsmG4ZTQWiDnZjfmrND
+xB4XsvZNPXnFkjdBENDROrbDRwm60SJDW73AbDbfq1IXAzSpuEyuRz61IyYKo0wq
+nmObJtVdIu3bVlWIlDXaP5Emk3d7ouCj5f8Kyeb8gm4pL3N6e0eI63hCaS39hhE6
+RLGh9HU9ht1kKfgcTwmB5b2HTPb4M6z1AmSIaMVqZTjIspsUgNF2+GBm3fOnOaiZ
+SEXWtgjMRXiIHbtU0va3LhSH5OSW0mh+L9oGUQDYnyuudnWGpulhqIp4qVkJRDDu
+41HpD83dV2uRtBLvc25AFHj7kXBflbO3gvGZVPYf1zVghQ==
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/server-crldir/a836cc2d.r0 b/src/test/ssl/ssl/server-crldir/a836cc2d.r0
new file mode 100644 (file)
index 0000000..717951c
--- /dev/null
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3Qgc2VydmVyIGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBBhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAbVuJXemxM6HLlIHGWlQvVmsmG4ZTQWiDnZjfmrND
+xB4XsvZNPXnFkjdBENDROrbDRwm60SJDW73AbDbfq1IXAzSpuEyuRz61IyYKo0wq
+nmObJtVdIu3bVlWIlDXaP5Emk3d7ouCj5f8Kyeb8gm4pL3N6e0eI63hCaS39hhE6
+RLGh9HU9ht1kKfgcTwmB5b2HTPb4M6z1AmSIaMVqZTjIspsUgNF2+GBm3fOnOaiZ
+SEXWtgjMRXiIHbtU0va3LhSH5OSW0mh+L9oGUQDYnyuudnWGpulhqIp4qVkJRDDu
+41HpD83dV2uRtBLvc25AFHj7kXBflbO3gvGZVPYf1zVghQ==
+-----END X509 CRL-----
index 7928de4e7c2de982b85ade1bc79ffb44553c4491..864f6e209f5d8d408eb1ef2b2c060214d044911e 100644 (file)
@@ -17,7 +17,7 @@ if ($ENV{with_ssl} ne 'openssl')
 }
 else
 {
-   plan tests => 93;
+   plan tests => 100;
 }
 
 #### Some configuration
@@ -215,12 +215,25 @@ test_connect_fails(
    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 =
@@ -346,7 +359,12 @@ test_connect_fails(
    $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(
@@ -545,6 +563,16 @@ test_connect_ok(
 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)
 {
index f5987a003efd67de0b13d4d29e10a0043767ffbe..5ec5e0dac8820fd6c703c05d83b9b7feb36fc341 100644 (file)
@@ -150,6 +150,8 @@ sub configure_test_server_for_ssl
    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;
@@ -167,14 +169,24 @@ sub switch_server_cert
    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;