From 5abf0c753c4310e03e9e9293164e76b32f903c12 Mon Sep 17 00:00:00 2001 From: Umar Hayat Date: Wed, 11 Mar 2020 13:38:56 +0500 Subject: [PATCH] Add support for CRL (Certificate Revocation List) Add new configuration variable ssl_crl_file to let the user configure path for CRL file. ssl_crl_file will be loaded at startup. If a certificate is revoked by CA and revoked entry is available in CRL file, client authentication will fail. --- 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 | 40 +++++++++++++ 12 files changed, 235 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/ssl.sgml b/doc/src/sgml/ssl.sgml index c7a2693..d5c095d 100644 --- a/doc/src/sgml/ssl.sgml +++ b/doc/src/sgml/ssl.sgml @@ -128,6 +128,25 @@ + + ssl_crl_file (string) + + ssl_crl_file configuration parameter + + + + + Specifies the name of the file containing the SSL server + certificate revocation list (CRL). The default is empty, + meaning no CRL file is loaded. + + + + This parameter can only be set at server start. + + + + ssl_ciphers (string) diff --git a/src/config/pool_config_variables.c b/src/config/pool_config_variables.c index 1c1736e..30114da 100644 --- a/src/config/pool_config_variables.c +++ b/src/config/pool_config_variables.c @@ -1070,6 +1070,16 @@ static struct config_string ConfigureNamesString[] = }, { + {"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.", CONFIG_VAR_TYPE_STRING, false, 0 diff --git a/src/include/pool_config.h b/src/include/pool_config.h index ec1bbf7..a14ead1 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 44060d8..6158ed8 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 3c7845d..de25b56 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 ce5e4da..b179129 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 f34b40f..ef84093 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 8474240..2cc7bda 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 e363432..673d698 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 <> 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 25728b0..126de0e 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 346477e..1177fec 100644 --- a/src/utils/pool_ssl.c +++ b/src/utils/pool_ssl.c @@ -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 -- 2.8.1