summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2016-04-12 18:14:08 +0200
committerLukas Slebodnik <lslebodn@redhat.com>2016-06-09 11:58:17 +0200
commit53ef8f81b60929a6c866efdd133627e7d7d61705 (patch)
treedec625c6cd01e15e73ace5d2e71054e95921e9f4
parentaa35995ef056aa8ae052a47c62c6750b7adf065e (diff)
downloadsssd-53ef8f81b60929a6c866efdd133627e7d7d61705.tar.gz
sssd-53ef8f81b60929a6c866efdd133627e7d7d61705.tar.xz
sssd-53ef8f81b60929a6c866efdd133627e7d7d61705.zip
p11: add OCSP default responder options
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-rw-r--r--src/man/sssd.conf.5.xml28
-rw-r--r--src/p11_child/p11_child_nss.c33
-rw-r--r--src/tests/cmocka/test_utils.c80
-rw-r--r--src/util/cert/nss/cert.c43
-rw-r--r--src/util/util.c60
-rw-r--r--src/util/util.h2
6 files changed, 242 insertions, 4 deletions
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 5396a490a..6cff0dc87 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -391,6 +391,34 @@
testing.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>ocsp_default_responder=URL</term>
+ <listitem>
+ <para>Sets the OCSP default responder
+ which should be used instead of the one
+ mentioned in the certificate. URL must
+ 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
+ ocsp_default_responder_signing_cert.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <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 availble in the systems NSS
+ database.</para>
+ <para>This option must be used together
+ with ocsp_default_responder.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</para>
<para>
diff --git a/src/p11_child/p11_child_nss.c b/src/p11_child/p11_child_nss.c
index be3f33981..feae88436 100644
--- a/src/p11_child/p11_child_nss.c
+++ b/src/p11_child/p11_child_nss.c
@@ -271,6 +271,27 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
PR_GetError());
return EIO;
}
+
+ if (cert_verify_opts->ocsp_default_responder != NULL
+ && cert_verify_opts->ocsp_default_responder_signing_cert != NULL) {
+ rv = CERT_SetOCSPDefaultResponder(handle,
+ cert_verify_opts->ocsp_default_responder,
+ cert_verify_opts->ocsp_default_responder_signing_cert);
+ if (rv != SECSuccess) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "CERT_SetOCSPDefaultResponder failed: [%d].\n",
+ PR_GetError());
+ return EIO;
+ }
+
+ rv = CERT_EnableOCSPDefaultResponder(handle);
+ if (rv != SECSuccess) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "CERT_EnableOCSPDefaultResponder failed: [%d].\n",
+ PR_GetError());
+ return EIO;
+ }
+ }
}
found_cert = NULL;
@@ -309,6 +330,18 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
}
}
+ /* Disable OCSP default responder so that NSS can shutdown properly */
+ if (cert_verify_opts->do_ocsp
+ && cert_verify_opts->ocsp_default_responder != NULL
+ && cert_verify_opts->ocsp_default_responder_signing_cert != NULL) {
+ rv = CERT_DisableOCSPDefaultResponder(handle);
+ if (rv != SECSuccess) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "CERT_DisableOCSPDefaultResponder failed: [%d].\n",
+ PR_GetError());
+ }
+ }
+
if (found_cert == NULL) {
DEBUG(SSSDBG_TRACE_ALL, "No certificate found.\n");
*cert = NULL;
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
index 3aea17f36..aaba2df6d 100644
--- a/src/tests/cmocka/test_utils.c
+++ b/src/tests/cmocka/test_utils.c
@@ -1487,6 +1487,83 @@ static void test_sss_unique_filename_destruct(void **state)
sss_unique_filename_test(test_ctx, true);
}
+static void test_parse_cert_verify_opts(void **state)
+{
+ int ret;
+ struct cert_verify_opts *cv_opts;
+
+ ret = parse_cert_verify_opts(global_talloc_context, NULL, &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);
+ talloc_free(cv_opts);
+
+ ret = parse_cert_verify_opts(global_talloc_context, "wedfkwefjk", &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);
+ talloc_free(cv_opts);
+
+ ret = parse_cert_verify_opts(global_talloc_context, "no_ocsp", &cv_opts);
+ assert_int_equal(ret, EOK);
+ assert_true(cv_opts->do_verification);
+ assert_false(cv_opts->do_ocsp);
+ assert_null(cv_opts->ocsp_default_responder);
+ assert_null(cv_opts->ocsp_default_responder_signing_cert);
+ talloc_free(cv_opts);
+
+ ret = parse_cert_verify_opts(global_talloc_context, "no_verification",
+ &cv_opts);
+ assert_int_equal(ret, EOK);
+ assert_false(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);
+ talloc_free(cv_opts);
+
+ ret = parse_cert_verify_opts(global_talloc_context,
+ "no_ocsp,no_verification", &cv_opts);
+ assert_int_equal(ret, EOK);
+ assert_false(cv_opts->do_verification);
+ assert_false(cv_opts->do_ocsp);
+ assert_null(cv_opts->ocsp_default_responder);
+ assert_null(cv_opts->ocsp_default_responder_signing_cert);
+ talloc_free(cv_opts);
+
+ ret = parse_cert_verify_opts(global_talloc_context,
+ "ocsp_default_responder=", &cv_opts);
+ assert_int_equal(ret, EINVAL);
+
+ ret = parse_cert_verify_opts(global_talloc_context,
+ "ocsp_default_responder_signing_cert=",
+ &cv_opts);
+ assert_int_equal(ret, EINVAL);
+
+ ret = parse_cert_verify_opts(global_talloc_context,
+ "ocsp_default_responder=abc", &cv_opts);
+ assert_int_equal(ret, EINVAL);
+
+ ret = parse_cert_verify_opts(global_talloc_context,
+ "ocsp_default_responder_signing_cert=def",
+ &cv_opts);
+ assert_int_equal(ret, EINVAL);
+
+ ret = parse_cert_verify_opts(global_talloc_context,
+ "ocsp_default_responder=abc,"
+ "ocsp_default_responder_signing_cert=def",
+ &cv_opts);
+ assert_int_equal(ret, EOK);
+ assert_true(cv_opts->do_verification);
+ 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");
+ talloc_free(cv_opts);
+}
+
int main(int argc, const char *argv[])
{
poptContext pc;
@@ -1566,6 +1643,9 @@ int main(int argc, const char *argv[])
cmocka_unit_test_setup_teardown(test_sss_unique_filename_destruct,
unique_file_test_setup,
unique_file_test_teardown),
+ cmocka_unit_test_setup_teardown(test_parse_cert_verify_opts,
+ setup_add_strings_lists,
+ teardown_add_strings_lists),
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */
diff --git a/src/util/cert/nss/cert.c b/src/util/cert/nss/cert.c
index 9c1c965dd..7bf9a8bfc 100644
--- a/src/util/cert/nss/cert.c
+++ b/src/util/cert/nss/cert.c
@@ -238,6 +238,7 @@ errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
NSSInitParameters parameters = { 0 };
parameters.length = sizeof (parameters);
SECStatus rv;
+ SECStatus rv_verify;
if (der_blob == NULL || der_size == 0) {
return EINVAL;
@@ -266,6 +267,27 @@ errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
PR_GetError());
return EIO;
}
+
+ if (cert_verify_opts->ocsp_default_responder != NULL
+ && cert_verify_opts->ocsp_default_responder_signing_cert != NULL) {
+ rv = CERT_SetOCSPDefaultResponder(handle,
+ cert_verify_opts->ocsp_default_responder,
+ cert_verify_opts->ocsp_default_responder_signing_cert);
+ if (rv != SECSuccess) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "CERT_SetOCSPDefaultResponder failed: [%d].\n",
+ PR_GetError());
+ return EIO;
+ }
+
+ rv = CERT_EnableOCSPDefaultResponder(handle);
+ if (rv != SECSuccess) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "CERT_EnableOCSPDefaultResponder failed: [%d].\n",
+ PR_GetError());
+ return EIO;
+ }
+ }
}
der_item.len = der_size;
@@ -279,9 +301,24 @@ errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
}
if (cert_verify_opts->do_verification) {
- rv = CERT_VerifyCertificateNow(handle, cert, PR_TRUE,
- certificateUsageSSLClient, NULL, NULL);
- if (rv != SECSuccess) {
+ rv_verify = CERT_VerifyCertificateNow(handle, cert, PR_TRUE,
+ certificateUsageSSLClient,
+ NULL, NULL);
+
+ /* Disable OCSP default responder so that NSS can shutdown properly */
+ if (cert_verify_opts->do_ocsp
+ && cert_verify_opts->ocsp_default_responder != NULL
+ && cert_verify_opts->ocsp_default_responder_signing_cert
+ != NULL) {
+ rv = CERT_DisableOCSPDefaultResponder(handle);
+ if (rv != SECSuccess) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "CERT_DisableOCSPDefaultResponder failed: [%d].\n",
+ PR_GetError());
+ }
+ }
+
+ if (rv_verify != SECSuccess) {
DEBUG(SSSDBG_CRIT_FAILURE, "CERT_VerifyCertificateNow failed [%d].\n",
PR_GetError());
ret = EACCES;
diff --git a/src/util/util.c b/src/util/util.c
index 2449a0ff3..d7d3ac90a 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -1111,7 +1111,7 @@ static struct cert_verify_opts *init_cert_verify_opts(TALLOC_CTX *mem_ctx)
{
struct cert_verify_opts *cert_verify_opts;
- cert_verify_opts = talloc(mem_ctx, struct cert_verify_opts);
+ cert_verify_opts = talloc_zero(mem_ctx, struct cert_verify_opts);
if (cert_verify_opts == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
return NULL;
@@ -1119,10 +1119,20 @@ static struct cert_verify_opts *init_cert_verify_opts(TALLOC_CTX *mem_ctx)
cert_verify_opts->do_ocsp = true;
cert_verify_opts->do_verification = true;
+ cert_verify_opts->ocsp_default_responder = NULL;
+ cert_verify_opts->ocsp_default_responder_signing_cert = NULL;
return cert_verify_opts;
}
+#define OCSP_DEFAUL_RESPONDER "ocsp_default_responder="
+#define OCSP_DEFAUL_RESPONDER_LEN (sizeof(OCSP_DEFAUL_RESPONDER) - 1)
+
+#define OCSP_DEFAUL_RESPONDER_SIGNING_CERT \
+ "ocsp_default_responder_signing_cert="
+#define OCSP_DEFAUL_RESPONDER_SIGNING_CERT_LEN \
+ (sizeof(OCSP_DEFAUL_RESPONDER_SIGNING_CERT) - 1)
+
errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts,
struct cert_verify_opts **_cert_verify_opts)
{
@@ -1168,6 +1178,41 @@ errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts,
"disabling verification completely. "
"This should not be used in production.\n");
cert_verify_opts->do_verification = false;
+ } else if (strncasecmp(opts[c], OCSP_DEFAUL_RESPONDER,
+ OCSP_DEFAUL_RESPONDER_LEN) == 0) {
+ cert_verify_opts->ocsp_default_responder =
+ talloc_strdup(cert_verify_opts,
+ &opts[c][OCSP_DEFAUL_RESPONDER_LEN]);
+ if (cert_verify_opts->ocsp_default_responder == NULL
+ || *cert_verify_opts->ocsp_default_responder == '\0') {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Failed to parse ocsp_default_responder option [%s].\n",
+ opts[c]);
+ ret = EINVAL;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_ALL, "Using OCSP default responder [%s]\n",
+ cert_verify_opts->ocsp_default_responder);
+ } else if (strncasecmp(opts[c],
+ OCSP_DEFAUL_RESPONDER_SIGNING_CERT,
+ OCSP_DEFAUL_RESPONDER_SIGNING_CERT_LEN) == 0) {
+ cert_verify_opts->ocsp_default_responder_signing_cert =
+ talloc_strdup(cert_verify_opts,
+ &opts[c][OCSP_DEFAUL_RESPONDER_SIGNING_CERT_LEN]);
+ if (cert_verify_opts->ocsp_default_responder_signing_cert == NULL
+ || *cert_verify_opts->ocsp_default_responder_signing_cert
+ == '\0') {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Failed to parse ocsp_default_responder_signing_cert "
+ "option [%s].\n", opts[c]);
+ ret = EINVAL;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_ALL,
+ "Using OCSP default responder signing cert nickname [%s]\n",
+ cert_verify_opts->ocsp_default_responder_signing_cert);
} else {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unsupported certificate verification option [%s], " \
@@ -1175,6 +1220,19 @@ errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts,
}
}
+ if ((cert_verify_opts->ocsp_default_responder == NULL
+ && cert_verify_opts->ocsp_default_responder_signing_cert != NULL)
+ || (cert_verify_opts->ocsp_default_responder != NULL
+ && cert_verify_opts->ocsp_default_responder_signing_cert == NULL)) {
+
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "ocsp_default_responder and ocsp_default_responder_signing_cert "
+ "must be used together.\n");
+
+ ret = EINVAL;
+ goto done;
+ }
+
ret = EOK;
done:
diff --git a/src/util/util.h b/src/util/util.h
index d7dc0aaf2..d36bb6086 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -330,6 +330,8 @@ char **parse_args(const char *str);
struct cert_verify_opts {
bool do_ocsp;
bool do_verification;
+ char *ocsp_default_responder;
+ char *ocsp_default_responder_signing_cert;
};
errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts,