URL: https://github.com/SSSD/sssd/pull/674 Author: sumit-bose Title: #674: p11_child: add OCSP and CRL check ot the OpenSSL version Action: synchronized
To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/674/head:pr674 git checkout pr674
From 9b807cd962983c971c3259e12ba613752ab81f84 Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Wed, 10 Oct 2018 15:37:16 +0200 Subject: [PATCH 1/2] p11_child: add OCSP check ot the OpenSSL version Related to https://pagure.io/SSSD/sssd/issue/3489 --- src/man/sssd.conf.5.xml | 26 ++- src/p11_child/p11_child_openssl.c | 335 ++++++++++++++++++++++++++++++ src/tests/cmocka/test_utils.c | 3 + src/util/util.c | 2 + 4 files changed, 359 insertions(+), 7 deletions(-) diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml index c8d53f01f3..5e3ae48d04 100644 --- a/src/man/sssd.conf.5.xml +++ b/src/man/sssd.conf.5.xml @@ -479,8 +479,8 @@ be replaced with the URL of the OCSP default responder e.g. http://example.com:80/ocsp.</para> - <para>This option must be used together - with + <para>(NSS Version) This option must be + used together with ocsp_default_responder_signing_cert. </para> </listitem> @@ -489,17 +489,29 @@ <term> ocsp_default_responder_signing_cert=NAME</term> <listitem> - <para>The nickname of the cert to trust - (expected) to sign the OCSP responses. - The certificate with the given nickname - must be available in the systems NSS - database.</para> + <para>(NSS Version) The nickname of the + cert to trust (expected) to sign the + OCSP responses. The certificate with + the given nickname must be available in + the systems NSS database.</para> <para>This option must be used together with ocsp_default_responder.</para> + <para>(OpenSSL version) This option is + currently ignored. All needed + certificates must be available in the + PEM file given by + pam_cert_db_path.</para> </listitem> </varlistentry> </variablelist> </para> + <para condition="with_nss"> + This man page was generated for the NSS version. + </para> + <para condition="with_openssl"> + This man page was generated for the OpenSSL + version. + </para> <para> Unknown options are reported but ignored. </para> diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c index 000e1c94f1..47c44cd57f 100644 --- a/src/p11_child/p11_child_openssl.c +++ b/src/p11_child/p11_child_openssl.c @@ -28,6 +28,7 @@ #include <openssl/x509.h> #include <openssl/err.h> #include <openssl/rand.h> +#include <openssl/ocsp.h> #include <p11-kit/p11-kit.h> #include <p11-kit/uri.h> @@ -42,8 +43,333 @@ struct p11_ctx { X509_STORE *x509_store; const char *ca_db; bool wait_for_card; + struct cert_verify_opts *cert_verify_opts; }; +static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host, + const char *path, + OCSP_REQUEST *req, int req_timeout) +{ + int fd; + int rv; + OCSP_REQ_CTX *ctx = NULL; + OCSP_RESPONSE *rsp = NULL; + fd_set confds; + struct timeval tv; + + if (req_timeout != -1) { + BIO_set_nbio(cbio, 1); + } + + rv = BIO_do_connect(cbio); + + if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) { + DEBUG(SSSDBG_OP_FAILURE, "Error connecting BIO\n"); + return NULL; + } + + if (BIO_get_fd(cbio, &fd) < 0) { + DEBUG(SSSDBG_OP_FAILURE, "Can't get connection fd\n"); + goto err; + } + + if (req_timeout != -1 && rv <= 0) { + FD_ZERO(&confds); + FD_SET(fd, &confds); + tv.tv_usec = 0; + tv.tv_sec = req_timeout; + rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv); + if (rv == 0) { + DEBUG(SSSDBG_OP_FAILURE, "Timeout on connect\n"); + return NULL; + } + } + + ctx = OCSP_sendreq_new(cbio, path, NULL, -1); + if (ctx == NULL) { + return NULL; + } + + if (OCSP_REQ_CTX_add1_header(ctx, "Host", host) == 0) { + goto err; + } + + if (!OCSP_REQ_CTX_set1_req(ctx, req)) { + goto err; + } + + for (;;) { + rv = OCSP_sendreq_nbio(&rsp, ctx); + if (rv != -1) + break; + if (req_timeout == -1) + continue; + FD_ZERO(&confds); + FD_SET(fd, &confds); + tv.tv_usec = 0; + tv.tv_sec = req_timeout; + if (BIO_should_read(cbio)) { + rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv); + } else if (BIO_should_write(cbio)) { + rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv); + } else { + DEBUG(SSSDBG_OP_FAILURE, "Unexpected retry condition\n"); + goto err; + } + if (rv == 0) { + DEBUG(SSSDBG_OP_FAILURE, "Timeout on request\n"); + break; + } + if (rv == -1) { + DEBUG(SSSDBG_OP_FAILURE, "Select error\n"); + break; + } + + } + err: + OCSP_REQ_CTX_free(ctx); + + return rsp; +} + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define TLS_client_method SSLv23_client_method +#define OCSP_REQUEST_add0_id OCSP_request_add0_id +#endif + +OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, + const char *host, const char *path, + const char *port, int use_ssl, + int req_timeout) +{ + BIO *cbio = NULL; + SSL_CTX *ctx = NULL; + OCSP_RESPONSE *resp = NULL; + + cbio = BIO_new_connect(host); + if (cbio == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Error creating connect BIO\n"); + goto end; + } + if (port != NULL) + BIO_set_conn_port(cbio, port); + if (use_ssl == 1) { + BIO *sbio; + ctx = SSL_CTX_new(TLS_client_method()); + if (ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Error creating SSL context.\n"); + goto end; + } + SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); + sbio = BIO_new_ssl(ctx, 1); + cbio = BIO_push(sbio, cbio); + } + + resp = query_responder(cbio, host, path, req, req_timeout); + if (resp == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Error querying OCSP responder\n"); + } + + end: + BIO_free_all(cbio); + SSL_CTX_free(ctx); + return resp; +} + +static errno_t do_ocsp(struct p11_ctx *p11_ctx, X509 *cert) +{ + OCSP_REQUEST *ocsp_req = NULL; + OCSP_RESPONSE *ocsp_resp = NULL; + OCSP_BASICRESP *ocsp_basic = NULL; + OCSP_CERTID *cid = NULL; + STACK_OF(OPENSSL_STRING) *ocsp_urls = NULL; + char *url_str; + X509 *issuer = NULL; + int req_timeout = -1; + int status; + int ret = EIO; + int reason; + ASN1_GENERALIZEDTIME *revtime; + ASN1_GENERALIZEDTIME *thisupd; + ASN1_GENERALIZEDTIME *nextupd; + long grace_time = (5 * 60); /* Allow 5 minutes time difference when + * checking the validity of the OCSP response */ + char *host = NULL; + char *path = NULL; + char *port = NULL; + int use_ssl; + X509_NAME *issuer_name = NULL; + X509_OBJECT *x509_obj; + + ocsp_urls = X509_get1_ocsp(cert); + if (ocsp_urls == NULL + && p11_ctx->cert_verify_opts->ocsp_default_responder == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "No OCSP URL in certificate and no default responder defined, " + "skipping OCSP check.\n"); + return EOK; + } + + if (p11_ctx->cert_verify_opts->ocsp_default_responder != NULL) { + url_str = p11_ctx->cert_verify_opts->ocsp_default_responder; + } else { + if (sk_OPENSSL_STRING_num(ocsp_urls) > 1) { + DEBUG(SSSDBG_CONF_SETTINGS, + "Found more than 1 OCSP URLs, just using the first.\n"); + } + + url_str = sk_OPENSSL_STRING_value(ocsp_urls, 0); + } + + DEBUG(SSSDBG_TRACE_ALL, "Using OCSP URL [%s].\n", url_str); + + ret = OCSP_parse_url(url_str, &host, &port, &path, &use_ssl); + if (ret != 1) { + DEBUG(SSSDBG_OP_FAILURE, "OCSP_parse_url failed to parse [%s].\n", + url_str); + ret = EIO; + goto done; + } + + issuer_name = X509_get_issuer_name(cert); + if (issuer_name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Certificate has no issuer, " + "cannot run OCSP check.\n"); + ret = EINVAL; + goto done; + } + + x509_obj = X509_OBJECT_retrieve_by_subject(p11_ctx->x509_store->objs, + X509_LU_X509, issuer_name); + if (x509_obj == NULL || x509_obj->type != X509_LU_X509) { + DEBUG(SSSDBG_CRIT_FAILURE, "Issuer not found.\n"); + ret = EIO; + goto done; + } + + issuer = x509_obj->data.x509; + + ocsp_req = OCSP_REQUEST_new(); + if (ocsp_req == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "OCSP_REQUEST_new failed.\n"); + ret = ENOMEM; + goto done; + } + + cid = OCSP_cert_to_id(EVP_sha1(), cert, issuer); + if (cid == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "OCSP_cert_to_id failed.\n"); + ret = EIO; + goto done; + } + + if (OCSP_REQUEST_add0_id(ocsp_req, cid) == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "OCSP_REQUEST_add0_id failed.\n"); + ret = EIO; + goto done; + } + + OCSP_request_add1_nonce(ocsp_req, NULL, -1); + + ocsp_resp = process_responder(ocsp_req, host, path, port, use_ssl, + req_timeout); + if (ocsp_resp == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "process_responder failed.\n"); + ret = EIO; + goto done; + } + + status = OCSP_response_status(ocsp_resp); + if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + DEBUG(SSSDBG_CRIT_FAILURE, "OCSP response error: [%d][%s].\n", + status, OCSP_response_status_str(status)); + ret = EIO; + goto done; + } + + ocsp_basic = OCSP_response_get1_basic(ocsp_resp); + if (ocsp_resp == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "OCSP_response_get1_basic failed.\n"); + ret = EIO; + goto done; + } + + switch (OCSP_check_nonce(ocsp_req, ocsp_basic)) { + case -1: + DEBUG(SSSDBG_CRIT_FAILURE, "No nonce in OCSP response. This might " + "indicate a replay attack or an OCSP responder which does not " + "support nonces. Accepting response.\n"); + break; + case 0: + DEBUG(SSSDBG_CRIT_FAILURE, "Nonce in OCSP response does not match the " + "one used in the request.\n"); + ret = EIO; + goto done; + break; + case 1: + DEBUG(SSSDBG_TRACE_ALL, "Nonce in OCSP response is the same as the one " + "used in the request.\n"); + break; + case 2: + case 3: + DEBUG(SSSDBG_CRIT_FAILURE, "Missing nonce in OCSP request, this should" + "never happen.\n"); + ret = EIO; + goto done; + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected result of OCSP_check_nonce.\n"); + } + + status = OCSP_basic_verify(ocsp_basic, NULL, p11_ctx->x509_store, 0); + if (status != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, "OCSP_base_verify failed to verify OCSP " + "response.\n"); + ret = EIO; + goto done; + } + + ret = OCSP_resp_find_status(ocsp_basic, cid, &status, &reason, + &revtime, &thisupd, &nextupd); + if (ret != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, "OCSP response does not contain status of " + "our certificate.\n"); + ret = EIO; + goto done; + } + + if (status != V_OCSP_CERTSTATUS_GOOD) { + DEBUG(SSSDBG_CRIT_FAILURE, "OCSP check failed with [%d][%s].\n", + status, OCSP_cert_status_str(status)); + if (status == V_OCSP_CERTSTATUS_REVOKED) { + DEBUG(SSSDBG_CRIT_FAILURE, "Certificate is revoked [%d][%s].\n", + reason, OCSP_crl_reason_str(reason)); + } + ret = EIO; + goto done; + } + + if (OCSP_check_validity(thisupd, nextupd, grace_time, -1) != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, "OCSP response is not valid anymore.\n"); + ret = EIO; + goto done; + } + + DEBUG(SSSDBG_TRACE_ALL, "OCSP check was successful.\n"); + ret = EOK; + +done: + OCSP_BASICRESP_free(ocsp_basic); + OCSP_RESPONSE_free(ocsp_resp); + OCSP_REQUEST_free(ocsp_req); + + OPENSSL_free(host); + OPENSSL_free(port); + OPENSSL_free(path); + X509_email_free(ocsp_urls); + + return ret; +} static char *get_pkcs11_uri(TALLOC_CTX *mem_ctx, CK_INFO *module_info, CK_SLOT_INFO *slot_info, CK_SLOT_ID slot_id, @@ -191,6 +517,7 @@ errno_t init_verification(struct p11_ctx *p11_ctx, } p11_ctx->x509_store = store; + p11_ctx->cert_verify_opts = cert_verify_opts; talloc_set_destructor(p11_ctx, talloc_free_x509_store); ret = EOK; @@ -262,6 +589,14 @@ bool do_verification(struct p11_ctx *p11_ctx, X509 *cert) goto done; } + if (p11_ctx->cert_verify_opts->do_ocsp) { + ret = do_ocsp(p11_ctx, cert); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "do_ocsp failed.\n"); + goto done; + } + } + res = true; done: diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c index 1a8699a2a8..c86e526e82 100644 --- a/src/tests/cmocka/test_utils.c +++ b/src/tests/cmocka/test_utils.c @@ -1612,6 +1612,8 @@ static void test_parse_cert_verify_opts(void **state) &cv_opts); assert_int_equal(ret, EINVAL); +/* Only NSS requires that both are set */ +#ifdef HAVE_NSS ret = parse_cert_verify_opts(global_talloc_context, "ocsp_default_responder=abc", &cv_opts); assert_int_equal(ret, EINVAL); @@ -1620,6 +1622,7 @@ static void test_parse_cert_verify_opts(void **state) "ocsp_default_responder_signing_cert=def", &cv_opts); assert_int_equal(ret, EINVAL); +#endif ret = parse_cert_verify_opts(global_talloc_context, "ocsp_default_responder=abc," diff --git a/src/util/util.c b/src/util/util.c index 53dd9a13ab..7f475fa9b5 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -1123,6 +1123,7 @@ errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts, } } +#ifdef HAVE_NSS if ((cert_verify_opts->ocsp_default_responder == NULL && cert_verify_opts->ocsp_default_responder_signing_cert != NULL) || (cert_verify_opts->ocsp_default_responder != NULL @@ -1135,6 +1136,7 @@ errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts, ret = EINVAL; goto done; } +#endif ret = EOK; From afdb22c11e15ba39319b5b4f8284fecadc973989 Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Thu, 11 Oct 2018 17:35:24 +0200 Subject: [PATCH 2/2] 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 --- 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 5e3ae48d04..bea25c6228 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 097e7fa07f..b992aeb71e 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 47c44cd57f..379f34aaf1 100644 --- a/src/p11_child/p11_child_openssl.c +++ b/src/p11_child/p11_child_openssl.c @@ -490,6 +490,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) { @@ -516,6 +517,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); @@ -525,7 +550,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 c86e526e82..cf1c2ae678 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 7f475fa9b5..cbe6a2870c 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 e3e9100972..7e9b3d6a6f 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,
_______________________________________________ sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org