From 53ef8f81b60929a6c866efdd133627e7d7d61705 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Tue, 12 Apr 2016 18:14:08 +0200 Subject: p11: add OCSP default responder options Reviewed-by: Jakub Hrozek --- src/util/cert/nss/cert.c | 43 +++++++++++++++++++++++++++++++--- src/util/util.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++- src/util/util.h | 2 ++ 3 files changed, 101 insertions(+), 4 deletions(-) (limited to 'src/util') 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, -- cgit