Merge branch 'fix/cluster-ssl-error-msg-6682' into support/2.0

fixes #6682
This commit is contained in:
Michael Friedrich 2014-08-04 17:29:59 +02:00
commit 9d318c359b
8 changed files with 104 additions and 21 deletions

View File

@ -595,7 +595,7 @@ int Main(void)
int rc = Application::GetInstance()->Run();
#ifndef _DEBUG
_exit(rc); // Yay, our static destructors are pretty much beyond repair at this point.
Application::Exit(rc);
#endif /* _DEBUG */
return rc;
@ -788,11 +788,11 @@ int main(int argc, char **argv)
};
StartServiceCtrlDispatcher(dispatchTable);
_exit(1);
Application::Exit(1);
}
#endif /* _WIN32 */
int rc = Main();
_exit(rc);
Application::Exit(rc);
}

View File

@ -112,6 +112,11 @@ Application::~Application(void)
m_Instance = NULL;
}
void Application::Exit(int rc)
{
_exit(rc); // Yay, our static destructors are pretty much beyond repair at this point.
}
void Application::InitializeBase(void)
{
#ifndef _WIN32
@ -282,7 +287,7 @@ mainloop:
lastLoop = now;
}
if (m_RequestRestart) {
m_RequestRestart = false; // we are now handling the request, once is enough
@ -295,7 +300,7 @@ mainloop:
goto mainloop;
}
Log(LogInformation, "Application", "Shutting down Icinga...");
DynamicObject::StopObjects();
Application::GetInstance()->OnShutdown();
@ -342,7 +347,7 @@ pid_t Application::StartReloadProcess(void)
Process::Ptr process = make_shared<Process>(Process::PrepareCommand(args));
process->SetTimeout(300);
process->Run(&ReloadProcessCallback);
return process->GetPID();
}
@ -706,7 +711,7 @@ void Application::UpdatePidFile(const String& filename, pid_t pid)
if (fcntl(fd, F_SETLK, &lock) < 0) {
Log(LogCritical, "Application", "Could not lock PID file. Make sure that only one instance of the application is running.");
_exit(EXIT_FAILURE);
Application::Exit(EXIT_FAILURE);
}
if (ftruncate(fd, 0) < 0) {
@ -1009,6 +1014,7 @@ void Application::MakeVariablesConstant(void)
ScriptVariable::GetByName("PrefixDir")->SetConstant(true);
ScriptVariable::GetByName("SysconfDir")->SetConstant(true);
ScriptVariable::GetByName("LocalStateDir")->SetConstant(true);
ScriptVariable::GetByName("RunDir")->SetConstant(true);
ScriptVariable::GetByName("PkgDataDir")->SetConstant(true);
ScriptVariable::GetByName("StatePath")->SetConstant(false);
ScriptVariable::GetByName("PidPath")->SetConstant(false);

View File

@ -46,6 +46,8 @@ public:
static Application::Ptr GetInstance(void);
static void Exit(int rc);
int Run(void);
/**
@ -128,7 +130,7 @@ protected:
pid_t StartReloadProcess(void);
virtual void OnShutdown(void);
private:
static Application *m_Instance; /**< The application instance. */

View File

@ -18,6 +18,10 @@
******************************************************************************/
#include "base/tlsutility.hpp"
#include "base/convert.hpp"
#include "base/logger_fwd.hpp"
#include "base/context.hpp"
namespace icinga
{
@ -72,6 +76,7 @@ static void InitializeOpenSSL(void)
*/
shared_ptr<SSL_CTX> MakeSSLContext(const String& pubkey, const String& privkey, const String& cakey)
{
std::ostringstream msgbuf;
InitializeOpenSSL();
shared_ptr<SSL_CTX> sslContext = shared_ptr<SSL_CTX>(SSL_CTX_new(TLSv1_method()), SSL_CTX_free);
@ -79,6 +84,8 @@ shared_ptr<SSL_CTX> MakeSSLContext(const String& pubkey, const String& privkey,
SSL_CTX_set_mode(sslContext.get(), SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
if (!SSL_CTX_use_certificate_chain_file(sslContext.get(), pubkey.CStr())) {
msgbuf << "Error with public key file '" << pubkey << "': " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("SSL_CTX_use_certificate_chain_file")
<< errinfo_openssl_error(ERR_get_error())
@ -86,6 +93,8 @@ shared_ptr<SSL_CTX> MakeSSLContext(const String& pubkey, const String& privkey,
}
if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.CStr(), SSL_FILETYPE_PEM)) {
msgbuf << "Error with private key file '" << privkey << "': " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("SSL_CTX_use_PrivateKey_file")
<< errinfo_openssl_error(ERR_get_error())
@ -93,12 +102,16 @@ shared_ptr<SSL_CTX> MakeSSLContext(const String& pubkey, const String& privkey,
}
if (!SSL_CTX_check_private_key(sslContext.get())) {
msgbuf << "Error checking private key '" << privkey << "': " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("SSL_CTX_check_private_key")
<< errinfo_openssl_error(ERR_get_error()));
}
if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.CStr(), NULL)) {
msgbuf << "Error loading and verifying locations in ca key file '" << cakey << "': " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("SSL_CTX_load_verify_locations")
<< errinfo_openssl_error(ERR_get_error())
@ -109,6 +122,8 @@ shared_ptr<SSL_CTX> MakeSSLContext(const String& pubkey, const String& privkey,
cert_names = SSL_load_client_CA_file(cakey.CStr());
if (cert_names == NULL) {
msgbuf << "Error loading client ca key file '" << cakey << "': " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("SSL_load_client_CA_file")
<< errinfo_openssl_error(ERR_get_error())
@ -128,18 +143,23 @@ shared_ptr<SSL_CTX> MakeSSLContext(const String& pubkey, const String& privkey,
*/
void AddCRLToSSLContext(const shared_ptr<SSL_CTX>& context, const String& crlPath)
{
std::ostringstream msgbuf;
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) {
msgbuf << "Error adding X509 store lookup: " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
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) {
msgbuf << "Error loading crl file '" << crlPath << "': " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("X509_LOOKUP_load_file")
<< errinfo_openssl_error(ERR_get_error())
@ -160,12 +180,15 @@ void AddCRLToSSLContext(const shared_ptr<SSL_CTX>& context, const String& crlPat
*/
String GetCertificateCN(const shared_ptr<X509>& certificate)
{
std::ostringstream msgbuf;
char buffer[256];
int rc = X509_NAME_get_text_by_NID(X509_get_subject_name(certificate.get()),
NID_commonName, buffer, sizeof(buffer));
if (rc == -1) {
msgbuf << "Error with x509 NAME getting text by NID: " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("X509_NAME_get_text_by_NID")
<< errinfo_openssl_error(ERR_get_error()));
@ -182,16 +205,21 @@ String GetCertificateCN(const shared_ptr<X509>& certificate)
*/
shared_ptr<X509> GetX509Certificate(const String& pemfile)
{
std::ostringstream msgbuf;
X509 *cert;
BIO *fpcert = BIO_new(BIO_s_file());
if (fpcert == NULL) {
msgbuf << "Error creating new BIO: " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("BIO_new")
<< errinfo_openssl_error(ERR_get_error()));
}
if (BIO_read_filename(fpcert, pemfile.CStr()) < 0) {
msgbuf << "Error reading pem file '" << pemfile << "': " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("BIO_read_filename")
<< errinfo_openssl_error(ERR_get_error())
@ -200,6 +228,8 @@ shared_ptr<X509> GetX509Certificate(const String& pemfile)
cert = PEM_read_bio_X509_AUX(fpcert, NULL, NULL, NULL);
if (cert == NULL) {
msgbuf << "Error on bio X509 AUX reading pem file '" << pemfile << "': " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("PEM_read_bio_X509_AUX")
<< errinfo_openssl_error(ERR_get_error())
@ -213,8 +243,8 @@ shared_ptr<X509> GetX509Certificate(const String& pemfile)
int MakeX509CSR(const char *cn, const char *keyfile, const char *csrfile)
{
InitializeOpenSSL();
InitializeOpenSSL();
RSA *rsa = RSA_generate_key(4096, RSA_F4, NULL, NULL);
BIO *bio = BIO_new(BIO_s_file());
@ -251,22 +281,29 @@ int MakeX509CSR(const char *cn, const char *keyfile, const char *csrfile)
String SHA256(const String& s)
{
std::ostringstream msgbuf;
SHA256_CTX context;
unsigned char digest[SHA256_DIGEST_LENGTH];
if (!SHA256_Init(&context)) {
msgbuf << "Error on SHA256 Init: " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("SHA256_Init")
<< errinfo_openssl_error(ERR_get_error()));
}
if (!SHA256_Update(&context, (unsigned char*)s.CStr(), s.GetLength())) {
msgbuf << "Error on SHA256 Update: " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("SHA256_Update")
<< errinfo_openssl_error(ERR_get_error()));
}
if (!SHA256_Final(digest, &context)) {
msgbuf << "Error on SHA256 Final: " << ERR_get_error() << ", \"" << ERR_error_string(ERR_get_error(), NULL) << "\"";
Log(LogCritical, "SSL", msgbuf.str());
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("SHA256_Final")
<< errinfo_openssl_error(ERR_get_error()));

View File

@ -898,6 +898,12 @@ void ApiEvents::RepositoryTimerHandler(void)
}
Endpoint::Ptr my_endpoint = Endpoint::GetLocalEndpoint();
if (!my_endpoint) {
Log(LogWarning, "ApiEvents", "No local endpoint defined. Bailing out.");
return;
}
Zone::Ptr my_zone = my_endpoint->GetZone();
Dictionary::Ptr params = make_shared<Dictionary>();
@ -965,14 +971,26 @@ Value ApiEvents::UpdateRepositoryAPIHandler(const MessageOrigin& origin, const D
String ApiEvents::GetVirtualHostName(const Host::Ptr& host)
{
String host_name = host->GetName();
if (host_name == "localhost")
host_name = Endpoint::GetLocalEndpoint()->GetName();
if (host_name == "localhost") {
Endpoint::Ptr local = Endpoint::GetLocalEndpoint();
if (!local)
return Empty;
host_name = local->GetName();
}
return host_name;
}
Host::Ptr ApiEvents::FindHostByVirtualName(const String& hostName)
{
if (hostName == Endpoint::GetLocalEndpoint()->GetName())
Endpoint::Ptr local = Endpoint::GetLocalEndpoint();
if (!local)
return Host::Ptr();
if (hostName == local->GetName())
return Host::GetByName("localhost");
else
return Host::GetByName(hostName);

View File

@ -102,7 +102,10 @@ void ApiListener::Start(void)
}
/* create the primary JSON-RPC listener */
AddListener(GetBindPort());
if (!AddListener(GetBindPort())) {
Log(LogCritical, "ApiListener", "Cannot add listener for port '" + Convert::ToString(GetBindPort()) + "'.");
Application::Exit(EXIT_FAILURE);
}
m_Timer = make_shared<Timer>();
m_Timer->OnTimerExpired.connect(boost::bind(&ApiListener::ApiTimerHandler, this));
@ -129,6 +132,10 @@ shared_ptr<SSL_CTX> ApiListener::GetSSLContext(void) const
Endpoint::Ptr ApiListener::GetMaster(void) const
{
Zone::Ptr zone = Zone::GetLocalZone();
if (!zone)
return Endpoint::Ptr();
std::vector<String> names;
BOOST_FOREACH(const Endpoint::Ptr& endpoint, zone->GetEndpoints())
@ -142,7 +149,12 @@ Endpoint::Ptr ApiListener::GetMaster(void) const
bool ApiListener::IsMaster(void) const
{
return GetMaster()->GetName() == GetIdentity();
Endpoint::Ptr master = GetMaster();
if (!master)
return false;
return master->GetName() == GetIdentity();
}
/**
@ -150,7 +162,7 @@ bool ApiListener::IsMaster(void) const
*
* @param service The port to listen on.
*/
void ApiListener::AddListener(const String& service)
bool ApiListener::AddListener(const String& service)
{
ObjectLock olock(this);
@ -158,7 +170,7 @@ void ApiListener::AddListener(const String& service)
if (!sslContext) {
Log(LogCritical, "ApiListener", "SSL context is required for AddListener()");
return;
return false;
}
std::ostringstream s;
@ -171,13 +183,15 @@ void ApiListener::AddListener(const String& service)
server->Bind(service, AF_UNSPEC);
} catch(std::exception&) {
Log(LogCritical, "ApiListener", "Cannot bind tcp socket on '" + service + "'.");
return;
return false;
}
boost::thread thread(boost::bind(&ApiListener::ListenerThreadProc, this, server));
thread.detach();
m_Servers.insert(server);
return true;
}
void ApiListener::ListenerThreadProc(const Socket::Ptr& server)
@ -209,7 +223,7 @@ void ApiListener::AddConnection(const Endpoint::Ptr& endpoint)
shared_ptr<SSL_CTX> sslContext = m_SSLContext;
if (!sslContext) {
Log(LogCritical, "ApiListener", "SSL context is required for AddListener()");
Log(LogCritical, "ApiListener", "SSL context is required for AddConnection()");
return;
}
}
@ -398,7 +412,10 @@ void ApiListener::ApiTimerHandler(void)
Utility::FormatDateTime("%Y/%m/%d %H:%M:%S", ts));
}
Log(LogNotice, "ApiListener", "Current zone master: " + GetMaster()->GetName());
Endpoint::Ptr master = GetMaster();
if (master)
Log(LogNotice, "ApiListener", "Current zone master: " + master->GetName());
std::vector<String> names;
BOOST_FOREACH(const Endpoint::Ptr& endpoint, DynamicType::GetObjects<Endpoint>())

View File

@ -79,7 +79,7 @@ private:
void ApiTimerHandler(void);
void AddListener(const String& service);
bool AddListener(const String& service);
void AddConnection(const Endpoint::Ptr& endpoint);
void NewClientHandler(const Socket::Ptr& client, ConnectionRole role);

View File

@ -42,6 +42,9 @@ static void AuthorityTimerHandler(void)
return;
Zone::Ptr my_zone = Zone::GetLocalZone();
if (!my_zone)
return;
Endpoint::Ptr my_endpoint = Endpoint::GetLocalEndpoint();
std::vector<Endpoint::Ptr> endpoints;