summaryrefslogtreecommitdiff
path: root/src/manager/service/ocsp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/manager/service/ocsp.cpp')
-rw-r--r--src/manager/service/ocsp.cpp667
1 files changed, 344 insertions, 323 deletions
diff --git a/src/manager/service/ocsp.cpp b/src/manager/service/ocsp.cpp
index aa5fa968..25219fc4 100644
--- a/src/manager/service/ocsp.cpp
+++ b/src/manager/service/ocsp.cpp
@@ -39,350 +39,371 @@
namespace CKM {
namespace {
-typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
+typedef std::unique_ptr<BIO, std::function<void(BIO *)>> BioUniquePtr;
-void BIO_write_and_free(BIO* bio)
+void BIO_write_and_free(BIO *bio)
{
- if (!bio)
- return;
+ if (!bio)
+ return;
- std::vector<char> message(1024);
- int size = BIO_read(bio, message.data(), message.size());
- if (size > 0) {
- message.resize(size);
- LogError("OCSP error description:" << std::string(message.begin(), message.end()));
- }
+ std::vector<char> message(1024);
+ int size = BIO_read(bio, message.data(), message.size());
- BIO_free_all(bio);
+ if (size > 0) {
+ message.resize(size);
+ LogError("OCSP error description:" << std::string(message.begin(),
+ message.end()));
+ }
+
+ BIO_free_all(bio);
}
} // namespace anonymous
OCSPModule::OCSPModule()
{
- // Do nothing.
+ // Do nothing.
}
OCSPModule::~OCSPModule()
{
- // Do nothing.
+ // Do nothing.
}
int OCSPModule::verify(const CertificateImplVector &certificateChain)
{
- bool unsupported = false; // ocsp is unsupported in certificate in chain (except root CA)
-
- // create trusted store
- X509_STACK_PTR trustedCerts = create_x509_stack();
-
- // skip first 2 certificates
- for (auto it = certificateChain.cbegin() + 2; it < certificateChain.cend(); it++) {
- if (it->empty()) {
- LogError("Error. Broken certificate chain.");
- return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
- }
- sk_X509_push(trustedCerts.get(), it->getX509());
- }
-
- for (int i = 0; i < static_cast<int>(certificateChain.size()) - 1; i++) {// except root certificate
- if (certificateChain[i].empty() || certificateChain[i+1].empty()) {
- LogError("Error. Broken certificate chain.");
- return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
- }
-
- X509 *cert = certificateChain[i].getX509();
- X509 *issuer = certificateChain[i+1].getX509();
-
- std::string url = certificateChain[i].getOCSPURL();
-
- if (url.empty()) {
- LogError("Certificate in certchain[" << i << "] does not provide OCSP extension.");
- unsupported = true;
- continue;
- }
-
- int result = ocsp_verify(cert, issuer, trustedCerts.get(), url);
- // remove first element from trustedCerts store
- sk_X509_delete(trustedCerts.get(), 0);
-
- if (result != CKM_API_OCSP_STATUS_GOOD) {
- LogError("Fail to OCSP certification check. Errorcode=[" << result <<
- "], on certChain[" << i << "]");
- return result;
- }
- }
-
- if (unsupported)
- return CKM_API_OCSP_STATUS_UNSUPPORTED;
-
- return CKM_API_OCSP_STATUS_GOOD;
+ bool unsupported =
+ false; // ocsp is unsupported in certificate in chain (except root CA)
+
+ // create trusted store
+ X509_STACK_PTR trustedCerts = create_x509_stack();
+
+ // skip first 2 certificates
+ for (auto it = certificateChain.cbegin() + 2; it < certificateChain.cend();
+ it++) {
+ if (it->empty()) {
+ LogError("Error. Broken certificate chain.");
+ return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
+ }
+
+ sk_X509_push(trustedCerts.get(), it->getX509());
+ }
+
+ for (int i = 0; i < static_cast<int>(certificateChain.size()) - 1;
+ i++) {// except root certificate
+ if (certificateChain[i].empty() || certificateChain[i + 1].empty()) {
+ LogError("Error. Broken certificate chain.");
+ return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
+ }
+
+ X509 *cert = certificateChain[i].getX509();
+ X509 *issuer = certificateChain[i + 1].getX509();
+
+ std::string url = certificateChain[i].getOCSPURL();
+
+ if (url.empty()) {
+ LogError("Certificate in certchain[" << i <<
+ "] does not provide OCSP extension.");
+ unsupported = true;
+ continue;
+ }
+
+ int result = ocsp_verify(cert, issuer, trustedCerts.get(), url);
+ // remove first element from trustedCerts store
+ sk_X509_delete(trustedCerts.get(), 0);
+
+ if (result != CKM_API_OCSP_STATUS_GOOD) {
+ LogError("Fail to OCSP certification check. Errorcode=[" << result <<
+ "], on certChain[" << i << "]");
+ return result;
+ }
+ }
+
+ if (unsupported)
+ return CKM_API_OCSP_STATUS_UNSUPPORTED;
+
+ return CKM_API_OCSP_STATUS_GOOD;
}
-int OCSPModule::ocsp_verify(X509 *cert, X509 *issuer, STACK_OF(X509) *trustedCerts, const std::string &constUrl)
+int OCSPModule::ocsp_verify(X509 *cert, X509 *issuer,
+ STACK_OF(X509) *trustedCerts, const std::string &constUrl)
{
- OCSP_REQUEST *req = NULL;
- OCSP_RESPONSE *resp = NULL;
- OCSP_BASICRESP *bs = NULL;
- OCSP_CERTID *certid = NULL;
- BIO *cbio = NULL;
- SSL_CTX *use_ssl_ctx = NULL;
- char *host = NULL, *port = NULL, *path = NULL;
- ASN1_GENERALIZEDTIME *rev = NULL;
- ASN1_GENERALIZEDTIME *thisupd = NULL;
- ASN1_GENERALIZEDTIME *nextupd = NULL;
- int use_ssl = 0;
- int ocspStatus = -1;
- int i = 0;
- long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
- char subj_buf[256];
- int reason = 0;
- // const char *reason_str = NULL;0
- X509_STORE *trustedStore = NULL;
- BioUniquePtr bioLogger(BIO_new(BIO_s_mem()), BIO_write_and_free);
-
- std::vector<char> url(constUrl.begin(), constUrl.end());
- url.push_back(0);
-
- if (!OCSP_parse_url(url.data(), &host, &port, &path, &use_ssl))
- /* report error */
- return CKM_API_OCSP_STATUS_INVALID_URL;
-
- LogDebug("Host: " << host);
- LogDebug("Port: " << port);
- LogDebug("Path: " << path);
- LogDebug("Use_ssl: " << use_ssl);
-
- cbio = BIO_new_connect(host);
- if (cbio == NULL) {
- /*BIO_printf(bio_err, "Error creating connect BIO\n");*/
- /* report error */
- return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
- }
-
- if (port != NULL)
- BIO_set_conn_port(cbio, port);
-
- if (use_ssl == 1) {
- BIO *sbio = NULL;
- use_ssl_ctx = SSL_CTX_new(SSLv23_client_method());
- if (use_ssl_ctx == NULL) {
- /* report error */
- return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
- }
-
- SSL_CTX_set_mode(use_ssl_ctx, SSL_MODE_AUTO_RETRY);
- sbio = BIO_new_ssl(use_ssl_ctx, 1);
- if (sbio == NULL) {
- /* report error */
- return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
- }
-
- cbio = BIO_push(sbio, cbio);
- if (cbio == NULL) {
- /* report error */
- return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
- }
- }
-
- if (BIO_do_connect(cbio) <= 0) {
- LogDebug("Error in BIO_do_connect.");
- ERR_print_errors(bioLogger.get());
- /* report error */
-
- /* free stuff */
- if (host != NULL)
- OPENSSL_free(host);
-
- if (port != NULL)
- OPENSSL_free(port);
-
- if (path != NULL)
- OPENSSL_free(path);
-
- host = port = path = NULL;
-
- if (use_ssl && use_ssl_ctx)
- SSL_CTX_free(use_ssl_ctx);
-
- use_ssl_ctx = NULL;
-
- if (cbio != NULL)
- BIO_free_all(cbio);
-
- cbio = NULL;
-
- return CKM_API_OCSP_STATUS_NET_ERROR;
- }
-
- req = OCSP_REQUEST_new();
- if (req == NULL) {
- LogDebug("Error in OCPS_REQUEST_new");
- return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
- }
-
- certid = OCSP_cert_to_id(NULL, cert, issuer);
- if (certid == NULL) {
- LogDebug("Error in OCSP_cert_to_id");
- return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
- }
-
- if (OCSP_request_add0_id(req, certid) == NULL) {
- LogDebug("Error in OCSP_request_add0_id");
- return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
- }
-
- resp = OCSP_sendreq_bio(cbio, path, req);
- /* free some stuff we no longer need */
- if (host != NULL)
- OPENSSL_free(host);
-
- if (port != NULL)
- OPENSSL_free(port);
-
- if (path != NULL)
- OPENSSL_free(path);
-
- host = port = path = NULL;
-
- if (use_ssl && use_ssl_ctx)
- SSL_CTX_free(use_ssl_ctx);
-
- use_ssl_ctx = NULL;
-
- if (cbio != NULL)
- BIO_free_all(cbio);
-
- cbio = NULL;
-
- if (!resp) {
- /*BIO_printf(bio_err, "Error querying OCSP responsder\n");*/
- /* report error */
- /* free stuff */
- OCSP_REQUEST_free(req);
- return CKM_API_OCSP_STATUS_NET_ERROR;
- }
-
- i = OCSP_response_status(resp);
-
- if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
- /* report error */
- ERR_print_errors(bioLogger.get());
- /* free stuff */
- OCSP_REQUEST_free(req);
- OCSP_RESPONSE_free(resp);
- return CKM_API_OCSP_STATUS_REMOTE_ERROR;
- }
-
- bs = OCSP_response_get1_basic(resp);
- if (!bs) {
- /* report error */
- ERR_print_errors(bioLogger.get());
- /* free stuff */
- OCSP_REQUEST_free(req);
- OCSP_RESPONSE_free(resp);
-
- LogDebug("Error in OCSP_response_get1_basic");
- return CKM_API_OCSP_STATUS_INVALID_RESPONSE;
- }
-
- if (trustedCerts != NULL) {
- trustedStore = X509_STORE_new();
-
- for (int tmpIdx = 0; tmpIdx < sk_X509_num(trustedCerts); tmpIdx++)
- X509_STORE_add_cert(trustedStore, sk_X509_value(trustedCerts, tmpIdx));
-
- X509_STORE_add_cert(trustedStore, issuer);
- }
-
- int response = OCSP_basic_verify(bs, NULL, trustedStore, 0);
- if (response <= 0) {
- OCSP_REQUEST_free(req);
- OCSP_RESPONSE_free(resp);
- OCSP_BASICRESP_free(bs);
- X509_STORE_free(trustedStore);
- ERR_print_errors(bioLogger.get());
- return CKM_API_OCSP_STATUS_INVALID_RESPONSE;
- }
-
- if ((i = OCSP_check_nonce(req, bs)) <= 0) {
- if (i == -1) {
- ERR_print_errors(bioLogger.get());
- } else {
- /* report error */
- ERR_print_errors(bioLogger.get());
- /* free stuff */
- OCSP_REQUEST_free(req);
- OCSP_RESPONSE_free(resp);
- OCSP_BASICRESP_free(bs);
- X509_STORE_free(trustedStore);
- LogDebug("Error in OCSP_check_nonce");
- return CKM_API_OCSP_STATUS_INVALID_RESPONSE;
- }
- }
-
- (void)X509_NAME_oneline(X509_get_subject_name(cert), subj_buf, 255);
- if (!OCSP_resp_find_status(bs, certid, &ocspStatus, &reason,
- &rev, &thisupd, &nextupd)) {
- /* report error */
- ERR_print_errors(bioLogger.get());
- /* free stuff */
- OCSP_RESPONSE_free(resp);
- OCSP_REQUEST_free(req);
- OCSP_BASICRESP_free(bs);
- X509_STORE_free(trustedStore);
-
- LogDebug("Error in OCSP_resp_find_status");
- return CKM_API_OCSP_STATUS_INVALID_RESPONSE;
- }
-
-
- /* Check validity: if invalid write to output BIO so we
- * know which response this refers to.
- */
- if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) {
- /* report error */
- ERR_print_errors(bioLogger.get());
- /* free stuff */
- OCSP_REQUEST_free(req);
- OCSP_RESPONSE_free(resp);
- OCSP_BASICRESP_free(bs);
- X509_STORE_free(trustedStore);
-
- LogDebug("Error in OCSP_check_validity");
- return CKM_API_OCSP_STATUS_INVALID_RESPONSE;
- }
-
- if (req != NULL) {
- OCSP_REQUEST_free(req);
- req = NULL;
- }
-
- if (resp != NULL) {
- OCSP_RESPONSE_free(resp);
- resp = NULL;
- }
-
- if (bs != NULL) {
- OCSP_BASICRESP_free(bs);
- bs = NULL;
- }
-
- if (trustedStore != NULL) {
- X509_STORE_free(trustedStore);
- trustedStore = NULL;
- }
-
- switch (ocspStatus) {
- case V_OCSP_CERTSTATUS_GOOD:
- return CKM_API_OCSP_STATUS_GOOD;
- case V_OCSP_CERTSTATUS_REVOKED:
- return CKM_API_OCSP_STATUS_REVOKED;
- case V_OCSP_CERTSTATUS_UNKNOWN:
- return CKM_API_OCSP_STATUS_UNKNOWN;
- default:
- LogError("Internal openssl error: Certificate status have value is out of bound.");
- return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
- }
+ OCSP_REQUEST *req = NULL;
+ OCSP_RESPONSE *resp = NULL;
+ OCSP_BASICRESP *bs = NULL;
+ OCSP_CERTID *certid = NULL;
+ BIO *cbio = NULL;
+ SSL_CTX *use_ssl_ctx = NULL;
+ char *host = NULL, *port = NULL, *path = NULL;
+ ASN1_GENERALIZEDTIME *rev = NULL;
+ ASN1_GENERALIZEDTIME *thisupd = NULL;
+ ASN1_GENERALIZEDTIME *nextupd = NULL;
+ int use_ssl = 0;
+ int ocspStatus = -1;
+ int i = 0;
+ long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
+ char subj_buf[256];
+ int reason = 0;
+ // const char *reason_str = NULL;0
+ X509_STORE *trustedStore = NULL;
+ BioUniquePtr bioLogger(BIO_new(BIO_s_mem()), BIO_write_and_free);
+
+ std::vector<char> url(constUrl.begin(), constUrl.end());
+ url.push_back(0);
+
+ if (!OCSP_parse_url(url.data(), &host, &port, &path, &use_ssl))
+ /* report error */
+ return CKM_API_OCSP_STATUS_INVALID_URL;
+
+ LogDebug("Host: " << host);
+ LogDebug("Port: " << port);
+ LogDebug("Path: " << path);
+ LogDebug("Use_ssl: " << use_ssl);
+
+ cbio = BIO_new_connect(host);
+
+ if (cbio == NULL) {
+ /*BIO_printf(bio_err, "Error creating connect BIO\n");*/
+ /* report error */
+ return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
+ }
+
+ if (port != NULL)
+ BIO_set_conn_port(cbio, port);
+
+ if (use_ssl == 1) {
+ BIO *sbio = NULL;
+ use_ssl_ctx = SSL_CTX_new(SSLv23_client_method());
+
+ if (use_ssl_ctx == NULL) {
+ /* report error */
+ return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
+ }
+
+ SSL_CTX_set_mode(use_ssl_ctx, SSL_MODE_AUTO_RETRY);
+ sbio = BIO_new_ssl(use_ssl_ctx, 1);
+
+ if (sbio == NULL) {
+ /* report error */
+ return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
+ }
+
+ cbio = BIO_push(sbio, cbio);
+
+ if (cbio == NULL) {
+ /* report error */
+ return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
+ }
+ }
+
+ if (BIO_do_connect(cbio) <= 0) {
+ LogDebug("Error in BIO_do_connect.");
+ ERR_print_errors(bioLogger.get());
+ /* report error */
+
+ /* free stuff */
+ if (host != NULL)
+ OPENSSL_free(host);
+
+ if (port != NULL)
+ OPENSSL_free(port);
+
+ if (path != NULL)
+ OPENSSL_free(path);
+
+ host = port = path = NULL;
+
+ if (use_ssl && use_ssl_ctx)
+ SSL_CTX_free(use_ssl_ctx);
+
+ use_ssl_ctx = NULL;
+
+ if (cbio != NULL)
+ BIO_free_all(cbio);
+
+ cbio = NULL;
+
+ return CKM_API_OCSP_STATUS_NET_ERROR;
+ }
+
+ req = OCSP_REQUEST_new();
+
+ if (req == NULL) {
+ LogDebug("Error in OCPS_REQUEST_new");
+ return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
+ }
+
+ certid = OCSP_cert_to_id(NULL, cert, issuer);
+
+ if (certid == NULL) {
+ LogDebug("Error in OCSP_cert_to_id");
+ return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
+ }
+
+ if (OCSP_request_add0_id(req, certid) == NULL) {
+ LogDebug("Error in OCSP_request_add0_id");
+ return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
+ }
+
+ resp = OCSP_sendreq_bio(cbio, path, req);
+
+ /* free some stuff we no longer need */
+ if (host != NULL)
+ OPENSSL_free(host);
+
+ if (port != NULL)
+ OPENSSL_free(port);
+
+ if (path != NULL)
+ OPENSSL_free(path);
+
+ host = port = path = NULL;
+
+ if (use_ssl && use_ssl_ctx)
+ SSL_CTX_free(use_ssl_ctx);
+
+ use_ssl_ctx = NULL;
+
+ if (cbio != NULL)
+ BIO_free_all(cbio);
+
+ cbio = NULL;
+
+ if (!resp) {
+ /*BIO_printf(bio_err, "Error querying OCSP responsder\n");*/
+ /* report error */
+ /* free stuff */
+ OCSP_REQUEST_free(req);
+ return CKM_API_OCSP_STATUS_NET_ERROR;
+ }
+
+ i = OCSP_response_status(resp);
+
+ if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
+ /* report error */
+ ERR_print_errors(bioLogger.get());
+ /* free stuff */
+ OCSP_REQUEST_free(req);
+ OCSP_RESPONSE_free(resp);
+ return CKM_API_OCSP_STATUS_REMOTE_ERROR;
+ }
+
+ bs = OCSP_response_get1_basic(resp);
+
+ if (!bs) {
+ /* report error */
+ ERR_print_errors(bioLogger.get());
+ /* free stuff */
+ OCSP_REQUEST_free(req);
+ OCSP_RESPONSE_free(resp);
+
+ LogDebug("Error in OCSP_response_get1_basic");
+ return CKM_API_OCSP_STATUS_INVALID_RESPONSE;
+ }
+
+ if (trustedCerts != NULL) {
+ trustedStore = X509_STORE_new();
+
+ for (int tmpIdx = 0; tmpIdx < sk_X509_num(trustedCerts); tmpIdx++)
+ X509_STORE_add_cert(trustedStore, sk_X509_value(trustedCerts, tmpIdx));
+
+ X509_STORE_add_cert(trustedStore, issuer);
+ }
+
+ int response = OCSP_basic_verify(bs, NULL, trustedStore, 0);
+
+ if (response <= 0) {
+ OCSP_REQUEST_free(req);
+ OCSP_RESPONSE_free(resp);
+ OCSP_BASICRESP_free(bs);
+ X509_STORE_free(trustedStore);
+ ERR_print_errors(bioLogger.get());
+ return CKM_API_OCSP_STATUS_INVALID_RESPONSE;
+ }
+
+ if ((i = OCSP_check_nonce(req, bs)) <= 0) {
+ if (i == -1) {
+ ERR_print_errors(bioLogger.get());
+ } else {
+ /* report error */
+ ERR_print_errors(bioLogger.get());
+ /* free stuff */
+ OCSP_REQUEST_free(req);
+ OCSP_RESPONSE_free(resp);
+ OCSP_BASICRESP_free(bs);
+ X509_STORE_free(trustedStore);
+ LogDebug("Error in OCSP_check_nonce");
+ return CKM_API_OCSP_STATUS_INVALID_RESPONSE;
+ }
+ }
+
+ (void)X509_NAME_oneline(X509_get_subject_name(cert), subj_buf, 255);
+
+ if (!OCSP_resp_find_status(bs, certid, &ocspStatus, &reason,
+ &rev, &thisupd, &nextupd)) {
+ /* report error */
+ ERR_print_errors(bioLogger.get());
+ /* free stuff */
+ OCSP_RESPONSE_free(resp);
+ OCSP_REQUEST_free(req);
+ OCSP_BASICRESP_free(bs);
+ X509_STORE_free(trustedStore);
+
+ LogDebug("Error in OCSP_resp_find_status");
+ return CKM_API_OCSP_STATUS_INVALID_RESPONSE;
+ }
+
+
+ /* Check validity: if invalid write to output BIO so we
+ * know which response this refers to.
+ */
+ if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) {
+ /* report error */
+ ERR_print_errors(bioLogger.get());
+ /* free stuff */
+ OCSP_REQUEST_free(req);
+ OCSP_RESPONSE_free(resp);
+ OCSP_BASICRESP_free(bs);
+ X509_STORE_free(trustedStore);
+
+ LogDebug("Error in OCSP_check_validity");
+ return CKM_API_OCSP_STATUS_INVALID_RESPONSE;
+ }
+
+ if (req != NULL) {
+ OCSP_REQUEST_free(req);
+ req = NULL;
+ }
+
+ if (resp != NULL) {
+ OCSP_RESPONSE_free(resp);
+ resp = NULL;
+ }
+
+ if (bs != NULL) {
+ OCSP_BASICRESP_free(bs);
+ bs = NULL;
+ }
+
+ if (trustedStore != NULL) {
+ X509_STORE_free(trustedStore);
+ trustedStore = NULL;
+ }
+
+ switch (ocspStatus) {
+ case V_OCSP_CERTSTATUS_GOOD:
+ return CKM_API_OCSP_STATUS_GOOD;
+
+ case V_OCSP_CERTSTATUS_REVOKED:
+ return CKM_API_OCSP_STATUS_REVOKED;
+
+ case V_OCSP_CERTSTATUS_UNKNOWN:
+ return CKM_API_OCSP_STATUS_UNKNOWN;
+
+ default:
+ LogError("Internal openssl error: Certificate status have value is out of bound.");
+ return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
+ }
}
} // namespace CKM