From 1a8969bb1b3dbd1d5ef7f29dd0fa2ddc8a50fa8b Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 11 Oct 2018 17:35:24 +0200
Subject: [PATCH 52/57] p11_child: add crl_file option for the OpenSSL build
In the NSS build a Certificate Revocation List (CRL) can just be added
to the NSS database. For OpenSSL a separate file is needed.
Related to https://pagure.io/SSSD/sssd/issue/3489
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 3c096c9ad6dad911d035cfdd802b5dda4710fc68)
---
src/man/sssd.conf.5.xml | 24 ++++++++++++++++++++++++
src/p11_child/p11_child_common.c | 12 ++++++------
src/p11_child/p11_child_openssl.c | 26 +++++++++++++++++++++++++-
src/tests/cmocka/test_utils.c | 16 ++++++++++++++++
src/util/util.c | 13 +++++++++++++
src/util/util.h | 1 +
6 files changed, 85 insertions(+), 7 deletions(-)
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 5e3ae48d04cc38ea54547a63c6c31795e12544c2..bea25c62286fa638bec47cb7404341be6190f410 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -503,6 +503,30 @@
pam_cert_db_path.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>crl_file=/PATH/TO/CRL/FILE</term>
+ <listitem>
+ <para>(NSS Version) This option is
+ ignored, please see
+ <citerefentry>
+ <refentrytitle>crlutil</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>
+ how to import a Certificate Revocation
+ List (CRL) into a NSS database.</para>
+
+ <para>(OpenSSL Version) Use the
+ Certificate Revocation List (CRL) from
+ the given file during the verification
+ of the certificate. The CRL must be
+ given in PEM format, see
+ <citerefentry>
+ <refentrytitle>crl</refentrytitle>
+ <manvolnum>1ssl</manvolnum>
+ </citerefentry>
+ for details.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</para>
<para condition="with_nss">
diff --git a/src/p11_child/p11_child_common.c b/src/p11_child/p11_child_common.c
index 097e7fa07fb4d90e087250aec9f971b4a2afdb52..b992aeb71ee6c8acc8792265aaa7bdcf0d06770d 100644
--- a/src/p11_child/p11_child_common.c
+++ b/src/p11_child/p11_child_common.c
@@ -48,7 +48,7 @@ static const char *op_mode_str(enum op_mode mode)
return "pre-auth";
break;
case OP_VERIFIY:
- return "verifiy";
+ return "verify";
break;
default:
return "unknown";
@@ -219,7 +219,7 @@ int main(int argc, const char *argv[])
case 'a':
if (mode != OP_NONE) {
fprintf(stderr,
- "\n--verifiy, --auth and --pre are mutually " \
+ "\n--verify, --auth and --pre are mutually " \
"exclusive and should be only used once.\n\n");
poptPrintUsage(pc, stderr, 0);
_exit(-1);
@@ -229,7 +229,7 @@ int main(int argc, const char *argv[])
case 'p':
if (mode != OP_NONE) {
fprintf(stderr,
- "\n--verifiy, --auth and --pre are mutually " \
+ "\n--verify, --auth and --pre are mutually " \
"exclusive and should be only used once.\n\n");
poptPrintUsage(pc, stderr, 0);
_exit(-1);
@@ -239,7 +239,7 @@ int main(int argc, const char *argv[])
case 'v':
if (mode != OP_NONE) {
fprintf(stderr,
- "\n--verifiy, --auth and --pre are mutually " \
+ "\n--verify, --auth and --pre are mutually " \
"exclusive and should be only used once.\n\n");
poptPrintUsage(pc, stderr, 0);
_exit(-1);
@@ -283,7 +283,7 @@ int main(int argc, const char *argv[])
if (mode == OP_NONE) {
fprintf(stderr, "\nMissing operation mode, either " \
- "--verifiy, --auth or --pre must be specified.\n\n");
+ "--verify, --auth or --pre must be specified.\n\n");
poptPrintUsage(pc, stderr, 0);
_exit(-1);
} else if (mode == OP_AUTH && pin_mode == PIN_NONE) {
@@ -350,7 +350,7 @@ int main(int argc, const char *argv[])
ret = parse_cert_verify_opts(main_ctx, verify_opts, &cert_verify_opts);
if (ret != EOK) {
- DEBUG(SSSDBG_FATAL_FAILURE, "Failed to parse verifiy option.\n");
+ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to parse verify option.\n");
goto fail;
}
diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c
index d66a2f82becfa24eae867a2f3df3e23263a5273c..9defdfc5a7acc70d0cea06d4919b06b93eb33c7b 100644
--- a/src/p11_child/p11_child_openssl.c
+++ b/src/p11_child/p11_child_openssl.c
@@ -501,6 +501,7 @@ errno_t init_verification(struct p11_ctx *p11_ctx,
X509_STORE *store = NULL;
unsigned long err;
X509_LOOKUP *lookup = NULL;
+ X509_VERIFY_PARAM *verify_param = NULL;
store = X509_STORE_new();
if (store == NULL) {
@@ -527,6 +528,30 @@ errno_t init_verification(struct p11_ctx *p11_ctx,
goto done;
}
+ if (cert_verify_opts->crl_file != NULL) {
+ verify_param = X509_VERIFY_PARAM_new();
+ if (verify_param == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "X509_VERIFY_PARAM_new failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ X509_VERIFY_PARAM_set_flags(verify_param, (X509_V_FLAG_CRL_CHECK
+ | X509_V_FLAG_CRL_CHECK_ALL));
+
+ X509_STORE_set1_param(store, verify_param);
+
+ ret = X509_load_crl_file(lookup, cert_verify_opts->crl_file,
+ X509_FILETYPE_PEM);
+ if (ret == 0) {
+ err = ERR_get_error();
+ DEBUG(SSSDBG_OP_FAILURE, "X509_load_crl_file failed [%lu][%s].\n",
+ err, ERR_error_string(err, NULL));
+ ret = EIO;
+ goto done;
+ }
+ }
+
p11_ctx->x509_store = store;
p11_ctx->cert_verify_opts = cert_verify_opts;
talloc_set_destructor(p11_ctx, talloc_free_x509_store);
@@ -536,7 +561,6 @@ errno_t init_verification(struct p11_ctx *p11_ctx,
done:
if (ret != EOK) {
X509_STORE_free(store);
- X509_LOOKUP_free(lookup);
}
return ret;
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
index c86e526e8299122c1c613c8459d3df0d9e4fc878..cf1c2ae6787cd1b011089b57d6bac320dadd60de 100644
--- a/src/tests/cmocka/test_utils.c
+++ b/src/tests/cmocka/test_utils.c
@@ -1567,6 +1567,7 @@ static void test_parse_cert_verify_opts(void **state)
assert_true(cv_opts->do_ocsp);
assert_null(cv_opts->ocsp_default_responder);
assert_null(cv_opts->ocsp_default_responder_signing_cert);
+ assert_null(cv_opts->crl_file);
talloc_free(cv_opts);
ret = parse_cert_verify_opts(global_talloc_context, "wedfkwefjk", &cv_opts);
@@ -1575,6 +1576,7 @@ static void test_parse_cert_verify_opts(void **state)
assert_true(cv_opts->do_ocsp);
assert_null(cv_opts->ocsp_default_responder);
assert_null(cv_opts->ocsp_default_responder_signing_cert);
+ assert_null(cv_opts->crl_file);
talloc_free(cv_opts);
ret = parse_cert_verify_opts(global_talloc_context, "no_ocsp", &cv_opts);
@@ -1583,6 +1585,7 @@ static void test_parse_cert_verify_opts(void **state)
assert_false(cv_opts->do_ocsp);
assert_null(cv_opts->ocsp_default_responder);
assert_null(cv_opts->ocsp_default_responder_signing_cert);
+ assert_null(cv_opts->crl_file);
talloc_free(cv_opts);
ret = parse_cert_verify_opts(global_talloc_context, "no_verification",
@@ -1592,6 +1595,7 @@ static void test_parse_cert_verify_opts(void **state)
assert_true(cv_opts->do_ocsp);
assert_null(cv_opts->ocsp_default_responder);
assert_null(cv_opts->ocsp_default_responder_signing_cert);
+ assert_null(cv_opts->crl_file);
talloc_free(cv_opts);
ret = parse_cert_verify_opts(global_talloc_context,
@@ -1601,6 +1605,7 @@ static void test_parse_cert_verify_opts(void **state)
assert_false(cv_opts->do_ocsp);
assert_null(cv_opts->ocsp_default_responder);
assert_null(cv_opts->ocsp_default_responder_signing_cert);
+ assert_null(cv_opts->crl_file);
talloc_free(cv_opts);
ret = parse_cert_verify_opts(global_talloc_context,
@@ -1633,6 +1638,17 @@ static void test_parse_cert_verify_opts(void **state)
assert_true(cv_opts->do_ocsp);
assert_string_equal(cv_opts->ocsp_default_responder, "abc");
assert_string_equal(cv_opts->ocsp_default_responder_signing_cert, "def");
+ assert_null(cv_opts->crl_file);
+ talloc_free(cv_opts);
+
+ ret = parse_cert_verify_opts(global_talloc_context, "crl_file=hij",
+ &cv_opts);
+ assert_int_equal(ret, EOK);
+ assert_true(cv_opts->do_verification);
+ assert_true(cv_opts->do_ocsp);
+ assert_null(cv_opts->ocsp_default_responder);
+ assert_null(cv_opts->ocsp_default_responder_signing_cert);
+ assert_string_equal(cv_opts->crl_file, "hij");
talloc_free(cv_opts);
}
diff --git a/src/util/util.c b/src/util/util.c
index 7f475fa9b5f5ddd69e80d5639380824cef82562c..cbe6a2870c302c51770ef5b526bd5bf8cc8df0e0 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -1024,6 +1024,7 @@ static struct cert_verify_opts *init_cert_verify_opts(TALLOC_CTX *mem_ctx)
cert_verify_opts->do_verification = true;
cert_verify_opts->ocsp_default_responder = NULL;
cert_verify_opts->ocsp_default_responder_signing_cert = NULL;
+ cert_verify_opts->crl_file = NULL;
return cert_verify_opts;
}
@@ -1035,6 +1036,8 @@ static struct cert_verify_opts *init_cert_verify_opts(TALLOC_CTX *mem_ctx)
"ocsp_default_responder_signing_cert="
#define OCSP_DEFAUL_RESPONDER_SIGNING_CERT_LEN \
(sizeof(OCSP_DEFAUL_RESPONDER_SIGNING_CERT) - 1)
+#define CRL_FILE "crl_file="
+#define CRL_FILE_LEN (sizeof(CRL_FILE) -1)
errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts,
struct cert_verify_opts **_cert_verify_opts)
@@ -1116,6 +1119,16 @@ errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts,
DEBUG(SSSDBG_TRACE_ALL,
"Using OCSP default responder signing cert nickname [%s]\n",
cert_verify_opts->ocsp_default_responder_signing_cert);
+ } else if (strncasecmp(opts[c], CRL_FILE, CRL_FILE_LEN) == 0) {
+ cert_verify_opts->crl_file = talloc_strdup(cert_verify_opts,
+ &opts[c][CRL_FILE_LEN]);
+ if (cert_verify_opts->crl_file == NULL
+ || *cert_verify_opts->crl_file == '\0') {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Failed to parse crl_file option [%s].\n", opts[c]);
+ ret = EINVAL;
+ goto done;
+ }
} else {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unsupported certificate verification option [%s], " \
diff --git a/src/util/util.h b/src/util/util.h
index e3e91009728cd8a5a92701220c06e8c378f47431..7e9b3d6a6fe323606ab9646b9757e725b5a4ef74 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -371,6 +371,7 @@ struct cert_verify_opts {
bool do_verification;
char *ocsp_default_responder;
char *ocsp_default_responder_signing_cert;
+ char *crl_file;
};
errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts,
--
2.14.4