dpward / rpms / sssd

Forked from rpms/sssd 3 years ago
Clone
Blob Blame History Raw
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