pgpool2.git / summary / log / commit / refs

commit    dc3116c797aab862635f2f7c73c6cbd35cd167cc
Author:   Tatsuo Ishii <ishii@sraoss.co.jp>
Date:     Sat Mar 14 02:54:38 2020 +0000

    Add support for SSL CRL (Certificate Revocation List).
    
    Patch created by Umar Hayat, along with Japanese document by Tatsuo
    Ishii.
    Discussion: https://www.pgpool.net/pipermail/pgpool-hackers/2020-February/003505.html


doc.ja/src/sgml/ssl.sgml | 18 ++++++ doc/src/sgml/ssl.sgml | 19 ++++++ src/config/pool_config_variables.c | 10 ++++ src/include/pool_config.h | 1 + src/sample/pgpool.conf.sample-logical | 3 + src/sample/pgpool.conf.sample-raw | 3 + src/sample/pgpool.conf.sample-replication | 3 + src/sample/pgpool.conf.sample-slony | 3 + src/sample/pgpool.conf.sample-stream | 3 + src/test/regression/tests/024.cert_auth/cert.sh | 72 +++++++++++++++++++++-- src/test/regression/tests/024.cert_auth/test.sh | 78 +++++++++++++++++++++++++ src/utils/pool_process_reporting.c | 5 ++ src/utils/pool_ssl.c | 42 ++++++++++++- 13 files changed, 254 insertions(+), 6 deletions(-) diff --git a/doc.ja/src/sgml/ssl.sgml b/doc.ja/src/sgml/ssl.sgml index 18e071475..755d40f1b 100644 --- a/doc.ja/src/sgml/ssl.sgml +++ b/doc.ja/src/sgml/ssl.sgml @@ -198,6 +198,24 @@ </listitem> </varlistentry> + <varlistentry id="guc-ssl-crl-file" xreflabel="ssl_crl_file"> + <term><varname>ssl_crl_file</varname> (<type>string</type>) + <indexterm> + <primary><varname>ssl_crl_file</varname>設定パラメータ</primary> + </indexterm> + </term> + <listitem> + <para> + SSSLサーバ証明書失効リスト(CRL)が入っているファイルのパス名を設定します。 + デフォルトは空で、この場合<acronym>CRL</acronym>ファイルは読み込まれません。 + </para> + + <para> + このパラメータはサーバ起動時にのみ設定可能です。 + </para> + </listitem> + </varlistentry> + <varlistentry id="guc-ssl-ciphers" xreflabel="ssl_ciphers"> <term><varname>ssl_ciphers</varname> (<type>string</type>) <indexterm> diff --git a/doc/src/sgml/ssl.sgml b/doc/src/sgml/ssl.sgml index c7a269317..0b04b2448 100644 --- a/doc/src/sgml/ssl.sgml +++ b/doc/src/sgml/ssl.sgml @@ -128,6 +128,25 @@ </listitem> </varlistentry> + <varlistentry id="guc-ssl-crl-file" xreflabel="ssl_crl_file"> + <term><varname>ssl_crl_file</varname> (<type>string</type>) + <indexterm> + <primary><varname>ssl_crl_file</varname> configuration parameter</primary> + </indexterm> + </term> + <listitem> + <para> + Specifies the path to the file containing the SSL server + certificate revocation list (CRL). The default is empty, + meaning no <acronym>CRL</acronym> file is loaded. + </para> + + <para> + This parameter can only be set at server start. + </para> + </listitem> + </varlistentry> + <varlistentry id="guc-ssl-ciphers" xreflabel="ssl_ciphers"> <term><varname>ssl_ciphers</varname> (<type>string</type>) <indexterm> diff --git a/src/config/pool_config_variables.c b/src/config/pool_config_variables.c index 1c1736e54..30114da19 100644 --- a/src/config/pool_config_variables.c +++ b/src/config/pool_config_variables.c @@ -1069,6 +1069,16 @@ static struct config_string ConfigureNamesString[] = NULL, NULL, NULL, NULL }, + { + {"ssl_crl_file", CFGCXT_INIT, SSL_CONFIG, + "Path to the SSL certificate revocation list file", + CONFIG_VAR_TYPE_STRING, false, 0 + }, + &g_pool_config.ssl_crl_file, + "", + NULL, NULL, NULL, NULL + }, + { {"ssl_ciphers", CFGCXT_INIT, SSL_CONFIG, "Allowed SSL ciphers.", diff --git a/src/include/pool_config.h b/src/include/pool_config.h index ec1bbf7db..a14ead1c4 100644 --- a/src/include/pool_config.h +++ b/src/include/pool_config.h @@ -362,6 +362,7 @@ typedef struct char *ssl_ca_cert; /* path to root (CA) certificate */ char *ssl_ca_cert_dir; /* path to directory containing CA * certificates */ + char *ssl_crl_file; /* path to the SSL certificate revocation list file */ char *ssl_ciphers; /* allowed ssl ciphers */ bool ssl_prefer_server_ciphers; /*Use SSL cipher preferences, rather than the client's*/ char *ssl_ecdh_curve; /* the curve to use in ECDH key exchange */ diff --git a/src/sample/pgpool.conf.sample-logical b/src/sample/pgpool.conf.sample-logical index 44060d8a1..6158ed89e 100644 --- a/src/sample/pgpool.conf.sample-logical +++ b/src/sample/pgpool.conf.sample-logical @@ -128,6 +128,9 @@ ssl = off #ssl_ca_cert_dir = '' # Directory containing CA root certificate(s) # (change requires restart) +#ssl_crl_file = '' + # Path to the SSL certificate revocation list file + # (change requires restart) ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # Allowed SSL ciphers diff --git a/src/sample/pgpool.conf.sample-raw b/src/sample/pgpool.conf.sample-raw index 3c7845d0f..de25b5697 100644 --- a/src/sample/pgpool.conf.sample-raw +++ b/src/sample/pgpool.conf.sample-raw @@ -129,6 +129,9 @@ ssl = off #ssl_ca_cert_dir = '' # Directory containing CA root certificate(s) # (change requires restart) +#ssl_crl_file = '' + # Path to the SSL certificate revocation list file + # (change requires restart) ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # Allowed SSL ciphers diff --git a/src/sample/pgpool.conf.sample-replication b/src/sample/pgpool.conf.sample-replication index ce5e4daf6..b17912918 100644 --- a/src/sample/pgpool.conf.sample-replication +++ b/src/sample/pgpool.conf.sample-replication @@ -124,6 +124,9 @@ ssl = off #ssl_ca_cert_dir = '' # Directory containing CA root certificate(s) # (change requires restart) +#ssl_crl_file = '' + # Path to the SSL certificate revocation list file + # (change requires restart) ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # Allowed SSL ciphers diff --git a/src/sample/pgpool.conf.sample-slony b/src/sample/pgpool.conf.sample-slony index f34b40fbb..ef840938f 100644 --- a/src/sample/pgpool.conf.sample-slony +++ b/src/sample/pgpool.conf.sample-slony @@ -125,6 +125,9 @@ ssl = off #ssl_ca_cert_dir = '' # Directory containing CA root certificate(s) # (change requires restart) +#ssl_crl_file = '' + # Path to the SSL certificate revocation list file + # (change requires restart) ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # Allowed SSL ciphers diff --git a/src/sample/pgpool.conf.sample-stream b/src/sample/pgpool.conf.sample-stream index 847424020..2cc7bda59 100644 --- a/src/sample/pgpool.conf.sample-stream +++ b/src/sample/pgpool.conf.sample-stream @@ -129,6 +129,9 @@ ssl = off #ssl_ca_cert_dir = '' # Directory containing CA root certificate(s) # (change requires restart) +#ssl_crl_file = '' + # Path to the SSL certificate revocation list file + # (change requires restart) ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # Allowed SSL ciphers diff --git a/src/test/regression/tests/024.cert_auth/cert.sh b/src/test/regression/tests/024.cert_auth/cert.sh index e3634323e..673d6980a 100755 --- a/src/test/regression/tests/024.cert_auth/cert.sh +++ b/src/test/regression/tests/024.cert_auth/cert.sh @@ -1,10 +1,72 @@ #!/usr/bin/env bash +[ -e "index.txt" ] && rm "index.txt" +touch index.txt +echo '1000' > serial +echo 'unique_subject = yes/no' > index.txt.attr +echo '1000' > crlnumber +if [ -d "certrecord" ]; then rm -Rf certrecord; fi +mkdir certrecord +if [ -d "newcerts" ]; then rm -Rf newcerts; fi +mkdir newcerts + +cat > crl_openssl.conf <<EOF + +[ ca ] +default_ca = CA_default + +[ CA_default ] +dir = . +database = index.txt +serial = serial +certs = newcerts +new_certs_dir = certrecord + +default_md = sha256 +crlnumber = crlnumber +default_crl_days = 365 + +name_opt = ca_default +cert_opt = ca_default +default_days = 375 +preserve = no +policy = policy_loose + +# The root key and root certificate. +private_key = root.key +certificate = root.crt + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[req] +distinguished_name = req_distinguished_name + +[req_distinguished_name] + +EOF + # Create root cert -openssl req -new -x509 -nodes -out root.crt -keyout root.key -days 365 -subj /CN=MyRootCA +openssl req -new -x509 -nodes -out root.crt -keyout root.key -config crl_openssl.conf -days 365 -subj /CN=MyRootCA # PostgreSQL/Pgpool cert -openssl req -new -out server.req -keyout server.key -nodes -subj "/CN=postgresql" -openssl x509 -req -in server.req -CAkey root.key -CA root.crt -days 365 -CAcreateserial -out server.crt +openssl req -new -out server.req -keyout server.key -config crl_openssl.conf -nodes -subj "/CN=postgresql" +openssl ca -batch -in server.req -config crl_openssl.conf -days 375 -notext -md sha256 -out server.crt + # Frontend Cert -openssl req -new -out postgresql.req -keyout frontend.key -nodes -subj "/CN=$USER" -openssl x509 -req -in postgresql.req -CAkey root.key -CA root.crt -days 365 -CAcreateserial -out frontend.crt +openssl req -new -out frontend.req -keyout frontend.key -config crl_openssl.conf -nodes -subj "/CN=$USER" +openssl ca -batch -in frontend.req -config crl_openssl.conf -days 375 -notext -md sha256 -out frontend.crt + +# Generate clean CRL (No revocation so far) +openssl ca -gencrl -config crl_openssl.conf -out server.crl -cert root.crt -keyfile root.key +# Revoke Frontend Cert +openssl ca -revoke frontend.crt -config crl_openssl.conf -keyfile root.key -cert root.crt -out root.crl +# Generate CRL after revocation +openssl ca -gencrl -config crl_openssl.conf -out server_revoked.crl -cert root.crt -keyfile root.key diff --git a/src/test/regression/tests/024.cert_auth/test.sh b/src/test/regression/tests/024.cert_auth/test.sh index 6fc59b656..1ff6ab435 100755 --- a/src/test/regression/tests/024.cert_auth/test.sh +++ b/src/test/regression/tests/024.cert_auth/test.sh @@ -14,6 +14,7 @@ export PGDATABASE=test dir=`pwd` SSL_KEY=$dir/server.key SSL_CRT=$dir/server.crt +SSL_CRL=$dir/server.crl ROOT_CRT=$dir/root.crt FRONTEND_KEY=$dir/frontend.key FRONTEND_CRT=$dir/frontend.crt @@ -52,6 +53,7 @@ wait_for_pgpool_startup export PGSSLCERT=$FRONTEND_CRT export PGSSLKEY=$FRONTEND_KEY +export PGSSLROOTCERT=$ROOT_CRT $PSQL -h localhost -c "select 1" test @@ -65,4 +67,80 @@ fi echo "Checking cert auth between Pgpool-II and frontend was ok." ./shutdownall + + +# Starting CRL verfication +# Adding valid CRL file in pgpool.conf file. +echo "ssl_crl_file = '$SSL_CRL'" >> etc/pgpool.conf + +# Check pgpool configuration is updated successfully +grep "server.crl" etc/pgpool.conf +if [ $? != 0 ];then + echo "pgpool.conf is not updated with CRL file." + ./shutdownall + exit 1 +fi + +# Start Server and PgPool +./startall + +export PGPORT=$PGPOOL_PORT + +wait_for_pgpool_startup + +export PGSSLCERT=$FRONTEND_CRT +export PGSSLKEY=$FRONTEND_KEY +export PGSSLROOTCERT=$ROOT_CRT + +$PSQL -h localhost -c "select 1" test + +grep "SSL certificate authentication for user" log/pgpool.log|grep successful +if [ $? != 0 ];then + echo "Checking cert auth between Pgpool-II and frontend with clean CRL failed." + ./shutdownall + exit 1 +fi + +echo "Checking cert auth between Pgpool-II and frontend with clean CRL was ok." + +./shutdownall + + +# Adding CRL file with revoked certification entry in pgpool.conf file. +echo "Updating pgpool.conf with revoked CRL file" + +sed -i 's/server.crl/server_revoked.crl/' etc/pgpool.conf + +# Check pgpool configuration is updated successfully +grep "server_revoked.crl" etc/pgpool.conf +if [ $? != 0 ];then + echo "pgpool.conf is not updated with revoked CRL file." + ./shutdownall + exit 1 +fi + +# Start Server and PgPool +./startall + +export PGPORT=$PGPOOL_PORT + +wait_for_pgpool_startup + +export PGSSLCERT=$FRONTEND_CRT +export PGSSLKEY=$FRONTEND_KEY +export PGSSLROOTCERT=$ROOT_CRT + +$PSQL -h localhost -c "select 1" test + +grep "certificate verify failed" log/pgpool.log +if [ $? != 0 ];then + echo "Checking cert auth between Pgpool-II and frontend with revoked entry in CRL failed." + ./shutdownall + exit 1 +fi + +echo "Checking cert auth between Pgpool-II and frontend with revoked entry in CRL was ok." + +./shutdownall + exit 0 diff --git a/src/utils/pool_process_reporting.c b/src/utils/pool_process_reporting.c index 25728b0ed..126de0e6c 100644 --- a/src/utils/pool_process_reporting.c +++ b/src/utils/pool_process_reporting.c @@ -259,6 +259,11 @@ get_config(int *nrows) StrNCpy(status[i].desc, "directory containing CA root certificate(s)", POOLCONFIG_MAXDESCLEN); i++; + StrNCpy(status[i].name, "ssl_crl_file", POOLCONFIG_MAXNAMELEN); + snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_crl_file); + StrNCpy(status[i].desc, "path to the SSL certificate revocation list file", POOLCONFIG_MAXDESCLEN); + i++; + StrNCpy(status[i].name, "ssl_ciphers", POOLCONFIG_MAXNAMELEN); snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_ciphers); StrNCpy(status[i].desc, "allowed SSL ciphers", POOLCONFIG_MAXDESCLEN); diff --git a/src/utils/pool_ssl.c b/src/utils/pool_ssl.c index 346477e34..59f4dcf9a 100644 --- a/src/utils/pool_ssl.c +++ b/src/utils/pool_ssl.c @@ -5,7 +5,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2016 PgPool Global Development Group + * Copyright (c) 2003-2020 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -675,7 +675,47 @@ SSL_ServerSide_init(void) pool_config->ssl_ca_cert, SSLerrmessage(ERR_get_error())))); goto error; } + } + + /*---------- + * Load the Certificate Revocation List (CRL). + * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html + *---------- + */ + if (pool_config->ssl_crl_file && strlen(pool_config->ssl_crl_file)) + { + 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, pool_config->ssl_crl_file, NULL) == 1) + { + /* OpenSSL 0.9.6 does not support X509_V_FLAG_CRL_CHECK */ +#ifdef X509_V_FLAG_CRL_CHECK + X509_STORE_set_flags(cvstore, + X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); +#else + ereport(LOG, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("SSL certificate revocation list file \"%s\" ignored", + pool_config->ssl_crl_file), + errdetail("SSL library does not support certificate revocation lists."))); +#endif + } + else + { + ereport(WARNING, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("could not load SSL certificate revocation list file \"%s\": %s", + pool_config->ssl_crl_file, SSLerrmessage(ERR_get_error())))); + goto error; + } + } + } + if (pool_config->ssl_ca_cert && strlen(pool_config->ssl_ca_cert)) + { /* * Always ask for SSL client cert, but don't fail if it's not * presented. We might fail such connections later, depending on what [parent: face0f278ddd]