From 5cd387016d3a75270a4b617306c4dedc565e0d0f Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Mon, 18 Mar 2013 19:02:42 +0100 Subject: [PATCH] Refactored #includes (Part 6). --- lib/base/Makefile.am | 2 + lib/base/exception.h | 19 ---- lib/base/i2-base.h | 12 --- lib/base/object.h | 7 ++ lib/base/stream.h | 2 - lib/base/stream_bio.h | 1 + lib/base/tlsstream.h | 1 + lib/base/tlsutility.cpp | 149 +++++++++++++++++++++++++++++++ lib/base/tlsutility.h | 59 ++++++++++++ lib/base/utility.cpp | 126 -------------------------- lib/base/utility.h | 9 +- lib/base/value.cpp | 24 +++++ lib/base/value.h | 41 +++------ lib/icinga/icingaapplication.cpp | 6 +- lib/icinga/icingaapplication.h | 1 + lib/remoting/endpointmanager.cpp | 3 +- 16 files changed, 260 insertions(+), 202 deletions(-) create mode 100644 lib/base/tlsutility.cpp create mode 100644 lib/base/tlsutility.h diff --git a/lib/base/Makefile.am b/lib/base/Makefile.am index 059cb1119..70f425f0f 100644 --- a/lib/base/Makefile.am +++ b/lib/base/Makefile.am @@ -81,6 +81,8 @@ libbase_la_SOURCES = \ timer.h \ tlsstream.cpp \ tlsstream.h \ + tlsutility.cpp \ + tlsutility.h \ unix.h \ unixsocket.cpp \ unixsocket.h \ diff --git a/lib/base/exception.h b/lib/base/exception.h index 85c2ef13a..174a377fc 100644 --- a/lib/base/exception.h +++ b/lib/base/exception.h @@ -85,25 +85,6 @@ inline std::string to_string(const errinfo_win32_error& e) } #endif /* _WIN32 */ -class I2_BASE_API openssl_error : virtual public std::exception, virtual public boost::exception { }; - -struct errinfo_openssl_error_; -typedef boost::error_info errinfo_openssl_error; - -inline std::string to_string(const errinfo_openssl_error& e) -{ - std::ostringstream tmp; - int code = e.value(); - - const char *message = ERR_error_string(code, NULL); - - if (message == NULL) - message = "Unknown error."; - - tmp << code << ", \"" << message << "\""; - return tmp.str(); -} - } #endif /* EXCEPTION_H */ diff --git a/lib/base/i2-base.h b/lib/base/i2-base.h index a7a9f898f..ab8fd5248 100644 --- a/lib/base/i2-base.h +++ b/lib/base/i2-base.h @@ -80,22 +80,10 @@ #include #include -#include -#include - -using boost::shared_ptr; -using boost::weak_ptr; -using boost::dynamic_pointer_cast; -using boost::static_pointer_cast; - #if defined(__APPLE__) && defined(__MACH__) # pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif -#include -#include -#include - #ifdef I2_BASE_BUILD # define I2_BASE_API I2_EXPORT #else /* I2_BASE_BUILD */ diff --git a/lib/base/object.h b/lib/base/object.h index d67dd223e..287172c31 100644 --- a/lib/base/object.h +++ b/lib/base/object.h @@ -22,8 +22,15 @@ #include "base/i2-base.h" #include +#include +#include #include +using boost::shared_ptr; +using boost::weak_ptr; +using boost::dynamic_pointer_cast; +using boost::static_pointer_cast; + namespace icinga { diff --git a/lib/base/stream.h b/lib/base/stream.h index 67fce2bf5..a3e1674c2 100644 --- a/lib/base/stream.h +++ b/lib/base/stream.h @@ -114,8 +114,6 @@ private: boost::exception_ptr m_Exception; }; -BIO *BIO_Stream_new(const Stream::Ptr& stream); - } #endif /* STREAM_H */ diff --git a/lib/base/stream_bio.h b/lib/base/stream_bio.h index 14ddf76a4..2199ed0ee 100644 --- a/lib/base/stream_bio.h +++ b/lib/base/stream_bio.h @@ -22,6 +22,7 @@ #include "base/i2-base.h" #include "base/stream.h" +#include "base/tlsutility.h" namespace icinga { diff --git a/lib/base/tlsstream.h b/lib/base/tlsstream.h index 3d1d1cf0d..96e3753ab 100644 --- a/lib/base/tlsstream.h +++ b/lib/base/tlsstream.h @@ -23,6 +23,7 @@ #include "base/i2-base.h" #include "base/stream.h" #include "base/fifo.h" +#include "base/tlsutility.h" namespace icinga { diff --git a/lib/base/tlsutility.cpp b/lib/base/tlsutility.cpp new file mode 100644 index 000000000..844b05ecd --- /dev/null +++ b/lib/base/tlsutility.cpp @@ -0,0 +1,149 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "base/tlsutility.h" + +using namespace icinga; + +static bool l_SSLInitialized = false; + +/** + * Initializes the OpenSSL library. + */ +static void InitializeOpenSSL(void) +{ + if (l_SSLInitialized) + return; + + SSL_library_init(); + SSL_load_error_strings(); + + l_SSLInitialized = true; +} + +/** + * Initializes an SSL context using the specified certificates. + * + * @param pubkey The public key. + * @param privkey The matching private key. + * @param cakey CA certificate chain file. + * @returns An SSL context. + */ +shared_ptr MakeSSLContext(const String& pubkey, const String& privkey, const String& cakey) +{ + InitializeOpenSSL(); + + shared_ptr sslContext = shared_ptr(SSL_CTX_new(TLSv1_method()), SSL_CTX_free); + + 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())) { + BOOST_THROW_EXCEPTION(openssl_error() + << boost::errinfo_api_function("SSL_CTX_use_certificate_chain_file") + << errinfo_openssl_error(ERR_get_error()) + << boost::errinfo_file_name(pubkey)); + } + + if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.CStr(), SSL_FILETYPE_PEM)) { + BOOST_THROW_EXCEPTION(openssl_error() + << boost::errinfo_api_function("SSL_CTX_use_PrivateKey_file") + << errinfo_openssl_error(ERR_get_error()) + << boost::errinfo_file_name(privkey)); + } + + if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.CStr(), NULL)) { + BOOST_THROW_EXCEPTION(openssl_error() + << boost::errinfo_api_function("SSL_CTX_load_verify_locations") + << errinfo_openssl_error(ERR_get_error()) + << boost::errinfo_file_name(cakey)); + } + + STACK_OF(X509_NAME) *cert_names; + + cert_names = SSL_load_client_CA_file(cakey.CStr()); + if (cert_names == NULL) { + BOOST_THROW_EXCEPTION(openssl_error() + << boost::errinfo_api_function("SSL_load_client_CA_file") + << errinfo_openssl_error(ERR_get_error()) + << boost::errinfo_file_name(cakey)); + } + + SSL_CTX_set_client_CA_list(sslContext.get(), cert_names); + + return sslContext; +} + +/** + * Retrieves the common name for an X509 certificate. + * + * @param certificate The X509 certificate. + * @returns The common name. + */ +String GetCertificateCN(const shared_ptr& certificate) +{ + 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) { + BOOST_THROW_EXCEPTION(openssl_error() + << boost::errinfo_api_function("X509_NAME_get_text_by_NID") + << errinfo_openssl_error(ERR_get_error())); + } + + return buffer; +} + +/** + * Retrieves an X509 certificate from the specified file. + * + * @param pemfile The filename. + * @returns An X509 certificate. + */ +shared_ptr GetX509Certificate(const String& pemfile) +{ + X509 *cert; + BIO *fpcert = BIO_new(BIO_s_file()); + + if (fpcert == NULL) { + 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) { + BOOST_THROW_EXCEPTION(openssl_error() + << boost::errinfo_api_function("BIO_read_filename") + << errinfo_openssl_error(ERR_get_error()) + << boost::errinfo_file_name(pemfile)); + } + + cert = PEM_read_bio_X509_AUX(fpcert, NULL, NULL, NULL); + if (cert == NULL) { + BOOST_THROW_EXCEPTION(openssl_error() + << boost::errinfo_api_function("PEM_read_bio_X509_AUX") + << errinfo_openssl_error(ERR_get_error())); + } + + BIO_free(fpcert); + + return shared_ptr(cert, X509_free); +} + diff --git a/lib/base/tlsutility.h b/lib/base/tlsutility.h new file mode 100644 index 000000000..ede21b02a --- /dev/null +++ b/lib/base/tlsutility.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#ifndef TLSUTILITY_H +#define TLSUTILITY_H + +#include "base/i2-base.h" +#include "base/object.h" +#include "base/qstring.h" +#include "base/exception.h" +#include +#include +#include + +namespace icinga +{ + +shared_ptr MakeSSLContext(const String& pubkey, const String& privkey, const String& cakey); +String GetCertificateCN(const shared_ptr& certificate); +shared_ptr GetX509Certificate(const String& pemfile); + +class I2_BASE_API openssl_error : virtual public std::exception, virtual public boost::exception { }; + +struct errinfo_openssl_error_; +typedef boost::error_info errinfo_openssl_error; + +inline std::string to_string(const errinfo_openssl_error& e) +{ + std::ostringstream tmp; + int code = e.value(); + + const char *message = ERR_error_string(code, NULL); + + if (message == NULL) + message = "Unknown error."; + + tmp << code << ", \"" << message << "\""; + return tmp.str(); +} + +} + +#endif /* TLSUTILITY_H */ diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index 7f91f6352..2d9539c0c 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -35,8 +35,6 @@ using namespace icinga; -bool I2_EXPORT Utility::m_SSLInitialized = false; - /** * Demangles a symbol name. * @@ -71,130 +69,6 @@ String Utility::GetTypeName(const std::type_info& ti) return DemangleSymbolName(ti.name()); } -/** - * Initializes the OpenSSL library. - */ -void Utility::InitializeOpenSSL(void) -{ - if (m_SSLInitialized) - return; - - SSL_library_init(); - SSL_load_error_strings(); - - m_SSLInitialized = true; -} - -/** - * Initializes an SSL context using the specified certificates. - * - * @param pubkey The public key. - * @param privkey The matching private key. - * @param cakey CA certificate chain file. - * @returns An SSL context. - */ -shared_ptr Utility::MakeSSLContext(const String& pubkey, const String& privkey, const String& cakey) -{ - InitializeOpenSSL(); - - shared_ptr sslContext = shared_ptr(SSL_CTX_new(TLSv1_method()), SSL_CTX_free); - - 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())) { - BOOST_THROW_EXCEPTION(openssl_error() - << boost::errinfo_api_function("SSL_CTX_use_certificate_chain_file") - << errinfo_openssl_error(ERR_get_error()) - << boost::errinfo_file_name(pubkey)); - } - - if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.CStr(), SSL_FILETYPE_PEM)) { - BOOST_THROW_EXCEPTION(openssl_error() - << boost::errinfo_api_function("SSL_CTX_use_PrivateKey_file") - << errinfo_openssl_error(ERR_get_error()) - << boost::errinfo_file_name(privkey)); - } - - if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.CStr(), NULL)) { - BOOST_THROW_EXCEPTION(openssl_error() - << boost::errinfo_api_function("SSL_CTX_load_verify_locations") - << errinfo_openssl_error(ERR_get_error()) - << boost::errinfo_file_name(cakey)); - } - - STACK_OF(X509_NAME) *cert_names; - - cert_names = SSL_load_client_CA_file(cakey.CStr()); - if (cert_names == NULL) { - BOOST_THROW_EXCEPTION(openssl_error() - << boost::errinfo_api_function("SSL_load_client_CA_file") - << errinfo_openssl_error(ERR_get_error()) - << boost::errinfo_file_name(cakey)); - } - - SSL_CTX_set_client_CA_list(sslContext.get(), cert_names); - - return sslContext; -} - -/** - * Retrieves the common name for an X509 certificate. - * - * @param certificate The X509 certificate. - * @returns The common name. - */ -String Utility::GetCertificateCN(const shared_ptr& certificate) -{ - 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) { - BOOST_THROW_EXCEPTION(openssl_error() - << boost::errinfo_api_function("X509_NAME_get_text_by_NID") - << errinfo_openssl_error(ERR_get_error())); - } - - return buffer; -} - -/** - * Retrieves an X509 certificate from the specified file. - * - * @param pemfile The filename. - * @returns An X509 certificate. - */ -shared_ptr Utility::GetX509Certificate(const String& pemfile) -{ - X509 *cert; - BIO *fpcert = BIO_new(BIO_s_file()); - - if (fpcert == NULL) { - 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) { - BOOST_THROW_EXCEPTION(openssl_error() - << boost::errinfo_api_function("BIO_read_filename") - << errinfo_openssl_error(ERR_get_error()) - << boost::errinfo_file_name(pemfile)); - } - - cert = PEM_read_bio_X509_AUX(fpcert, NULL, NULL, NULL); - if (cert == NULL) { - BOOST_THROW_EXCEPTION(openssl_error() - << boost::errinfo_api_function("PEM_read_bio_X509_AUX") - << errinfo_openssl_error(ERR_get_error())); - } - - BIO_free(fpcert); - - return shared_ptr(cert, X509_free); -} - /** * Performs wildcard pattern matching. * diff --git a/lib/base/utility.h b/lib/base/utility.h index 0248a14c6..f0b73225c 100644 --- a/lib/base/utility.h +++ b/lib/base/utility.h @@ -21,6 +21,7 @@ #define UTILITY_H #include "base/i2-base.h" +#include "base/object.h" #include "base/qstring.h" #include #include @@ -39,10 +40,6 @@ public: static String DemangleSymbolName(const String& sym); static String GetTypeName(const std::type_info& ti); - static shared_ptr MakeSSLContext(const String& pubkey, const String& privkey, const String& cakey); - static String GetCertificateCN(const shared_ptr& certificate); - static shared_ptr GetX509Certificate(const String& pemfile); - static bool Match(const String& pattern, const String& text); static String DirName(const String& path); @@ -80,11 +77,7 @@ public: static void SetNonBlockingSocket(SOCKET s); private: - static bool m_SSLInitialized; - Utility(void); - - static void InitializeOpenSSL(void); }; } diff --git a/lib/base/value.cpp b/lib/base/value.cpp index cd6144958..f4e07b0cc 100644 --- a/lib/base/value.cpp +++ b/lib/base/value.cpp @@ -28,6 +28,30 @@ using namespace icinga; Value Empty; +Value::Value(void) + : m_Value() +{ } + +Value::Value(int value) + : m_Value(value) +{ } + +Value::Value(long value) + : m_Value(double(value)) +{ } + +Value::Value(double value) + : m_Value(value) +{ } + +Value::Value(const String& value) + : m_Value(value) +{ } + +Value::Value(const char *value) + : m_Value(String(value)) +{ } + /** * Checks whether the variant is empty. * diff --git a/lib/base/value.h b/lib/base/value.h index 393ae7b76..0554a5178 100644 --- a/lib/base/value.h +++ b/lib/base/value.h @@ -22,7 +22,8 @@ #include "base/object.h" #include "base/qstring.h" -#include +#include +#include struct cJSON; @@ -50,29 +51,12 @@ enum ValueType class I2_BASE_API Value { public: - inline Value(void) - : m_Value() - { } - - inline Value(int value) - : m_Value(value) - { } - - inline Value(long value) - : m_Value(double(value)) - { } - - inline Value(double value) - : m_Value(value) - { } - - inline Value(const String& value) - : m_Value(value) - { } - - inline Value(const char *value) - : m_Value(String(value)) - { } + Value(void); + Value(int value); + Value(long value); + Value(double value); + Value(const String& value); + Value(const char *value); template inline Value(const shared_ptr& value) @@ -81,12 +65,7 @@ public: if (!value) return; - Object::Ptr object = dynamic_pointer_cast(value); - - if (!object) - BOOST_THROW_EXCEPTION(std::invalid_argument("shared_ptr value type must inherit from Object class.")); - - m_Value = object; + m_Value = static_pointer_cast(value); } operator double(void) const; @@ -106,7 +85,7 @@ public: return object; } - bool IsEmpty(void) const; +bool IsEmpty(void) const; bool IsScalar(void) const; bool IsObject(void) const; diff --git a/lib/icinga/icingaapplication.cpp b/lib/icinga/icingaapplication.cpp index 965371e42..4200edcd8 100644 --- a/lib/icinga/icingaapplication.cpp +++ b/lib/icinga/icingaapplication.cpp @@ -63,12 +63,12 @@ int IcingaApplication::Main(void) if (!GetCertificateFile().IsEmpty() && !GetCAFile().IsEmpty()) { /* set up SSL context */ - shared_ptr cert = Utility::GetX509Certificate(GetCertificateFile()); - String identity = Utility::GetCertificateCN(cert); + shared_ptr cert = GetX509Certificate(GetCertificateFile()); + String identity = GetCertificateCN(cert); Log(LogInformation, "icinga", "My identity: " + identity); EndpointManager::GetInstance()->SetIdentity(identity); - m_SSLContext = Utility::MakeSSLContext(GetCertificateFile(), GetCertificateFile(), GetCAFile()); + m_SSLContext = MakeSSLContext(GetCertificateFile(), GetCertificateFile(), GetCAFile()); EndpointManager::GetInstance()->SetSSLContext(m_SSLContext); } diff --git a/lib/icinga/icingaapplication.h b/lib/icinga/icingaapplication.h index edb36eedf..9e6a5610a 100644 --- a/lib/icinga/icingaapplication.h +++ b/lib/icinga/icingaapplication.h @@ -22,6 +22,7 @@ #include "icinga/i2-icinga.h" #include "base/application.h" +#include "base/tlsutility.h" namespace icinga { diff --git a/lib/remoting/endpointmanager.cpp b/lib/remoting/endpointmanager.cpp index 980076094..50871ca33 100644 --- a/lib/remoting/endpointmanager.cpp +++ b/lib/remoting/endpointmanager.cpp @@ -23,6 +23,7 @@ #include "base/logger_fwd.h" #include "base/convert.h" #include "base/utility.h" +#include "base/tlsutility.h" #include #include @@ -187,7 +188,7 @@ void EndpointManager::ClientConnectedHandler(const Stream::Ptr& client, const St m_PendingClients.erase(tlsStream); shared_ptr cert = tlsStream->GetPeerCertificate(); - String identity = Utility::GetCertificateCN(cert); + String identity = GetCertificateCN(cert); Log(LogInformation, "icinga", "New client connection at " + peerAddress + " for identity '" + identity + "'");