diff --git a/components/cluster/cluster-type.conf b/components/cluster/cluster-type.conf index aa05d15f9..9b881e478 100644 --- a/components/cluster/cluster-type.conf +++ b/components/cluster/cluster-type.conf @@ -27,6 +27,8 @@ type ClusterListener { %attribute string "ca_path", %require "ca_path", + %attribute string "crl_path", + %attribute string "bind_host", %attribute string "bind_port", diff --git a/components/cluster/clusterlistener.cpp b/components/cluster/clusterlistener.cpp index 82d7e2153..634ee0141 100644 --- a/components/cluster/clusterlistener.cpp +++ b/components/cluster/clusterlistener.cpp @@ -61,6 +61,9 @@ void ClusterListener::Start(void) m_SSLContext = MakeSSLContext(GetCertPath(), GetKeyPath(), GetCaPath()); + if (!GetCrlPath().IsEmpty()) + AddCRLToSSLContext(m_SSLContext, GetCrlPath()); + /* create the primary JSON-RPC listener */ if (!GetBindPort().IsEmpty()) AddListener(GetBindPort()); diff --git a/components/cluster/clusterlistener.ti b/components/cluster/clusterlistener.ti index 420a39efa..ac54697b1 100644 --- a/components/cluster/clusterlistener.ti +++ b/components/cluster/clusterlistener.ti @@ -8,6 +8,7 @@ class ClusterListener : DynamicObject [config] String cert_path; [config] String key_path; [config] String ca_path; + [config] String crl_path; [config] String bind_host; [config] String bind_port; [config] Array::Ptr peers; diff --git a/doc/4.3-object-types.md b/doc/4.3-object-types.md index aead93bc3..1526bae10 100644 --- a/doc/4.3-object-types.md +++ b/doc/4.3-object-types.md @@ -826,6 +826,7 @@ Attributes: cert\_path |**Required.** Path to the public key. key\_path |**Required.** Path to the private key. ca\_path |**Required.** Path to the CA certificate file. + crl\_path |**Optional.** Path to the CRL file. bind\_host |**Optional.** The IP address the cluster listener should be bound to. bind\_port |**Optional.** The port the cluster listener should be bound to. peers |**Optional.** A list of diff --git a/lib/base/tlsutility.cpp b/lib/base/tlsutility.cpp index 586e82a40..52efeb3f7 100644 --- a/lib/base/tlsutility.cpp +++ b/lib/base/tlsutility.cpp @@ -98,6 +98,38 @@ shared_ptr MakeSSLContext(const String& pubkey, const String& privkey, return sslContext; } +/** + * Loads a CRL and appends its certificates to the specified SSL context. + * + * @param context The SSL context. + * @param crlPath The path to the CRL file. + */ +void AddCRLToSSLContext(const shared_ptr& context, const String& crlPath) +{ + X509_STORE *x509_store = SSL_CTX_get_cert_store(context.get()); + + X509_LOOKUP *lookup; + lookup = X509_STORE_add_lookup(x509_store, X509_LOOKUP_file()); + + if (!lookup) { + BOOST_THROW_EXCEPTION(openssl_error() + << boost::errinfo_api_function("X509_STORE_add_lookup") + << errinfo_openssl_error(ERR_get_error())); + } + + if (X509_LOOKUP_load_file(lookup, crlPath.CStr(), X509_FILETYPE_PEM) != 0) { + BOOST_THROW_EXCEPTION(openssl_error() + << boost::errinfo_api_function("X509_LOOKUP_load_file") + << errinfo_openssl_error(ERR_get_error()) + << boost::errinfo_file_name(crlPath)); + } + + X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); + SSL_CTX_set1_param(context.get(), param); + X509_VERIFY_PARAM_free(param); +} + /** * Retrieves the common name for an X509 certificate. * diff --git a/lib/base/tlsutility.h b/lib/base/tlsutility.h index e0eb4e971..ee34d6c8c 100644 --- a/lib/base/tlsutility.h +++ b/lib/base/tlsutility.h @@ -34,6 +34,7 @@ namespace icinga { shared_ptr I2_BASE_API MakeSSLContext(const String& pubkey, const String& privkey, const String& cakey); +void I2_BASE_API AddCRLToSSLContext(const shared_ptr& context, const String& crlPath); String I2_BASE_API GetCertificateCN(const shared_ptr& certificate); shared_ptr I2_BASE_API GetX509Certificate(const String& pemfile); String I2_BASE_API SHA256(const String& s);