diff --git a/CMakeLists.txt b/CMakeLists.txt index 970da3d50..7f80c1e44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,13 +40,6 @@ file(READ "${CMAKE_CURRENT_SOURCE_DIR}/COPYING.Exceptions" ICINGA2_LICENSE_ADDIT set(ICINGA2_LICENSE "${ICINGA2_LICENSE_GPL}\n\n---\n\n${ICINGA2_LICENSE_ADDITIONS}") file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt" ${ICINGA2_LICENSE}) -set(CPACK_PACKAGE_CONTACT "Icinga Development Team") -set(CPACK_PACKAGE_VERSION ${ICINGA2_VERSION}) -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt") -set(CPACK_WIX_UPGRADE_GUID "68C75073-7CEF-4FC9-8DA5-581758729696") -set(CPACK_SOURCE_IGNORE_FILES "/.git/" "/debian/" "/.vagrant/" "/release/" "/debug/" "/build/" ) -include(CPack) - include(GetGitRevisionDescription) git_describe(GIT_VERSION --tags) if(GIT_VERSION MATCHES "-NOTFOUND$") @@ -56,13 +49,16 @@ else() configure_file(${CMAKE_CURRENT_BINARY_DIR}/icinga-version.h ${CMAKE_CURRENT_SOURCE_DIR}/icinga-version.h.fallback COPYONLY) endif() -set(CPACK_PACKAGE_CONTACT "Icinga Development Team") +set(CPACK_PACKAGE_NAME "Icinga2") +set(CPACK_PACKAGE_VENDOR "Icinga Development Team") set(CPACK_PACKAGE_VERSION ${ICINGA2_VERSION}) +set(CPACK_NSIS_DISPLAY_NAME "Icinga 2") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "ICINGA2") set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/icinga-app\\\\icinga.ico") set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/icinga-app\\\\icinga.ico") set(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/icinga-app\\\\icinga.ico") +set(CPACK_NSIS_INSTALLED_ICON_NAME "sbin\\\\icinga2.exe") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt") -set(CPACK_WIX_UPGRADE_GUID "68C75073-7CEF-4FC9-8DA5-581758729696") set(CPACK_SOURCE_IGNORE_FILES "/.git/" "/debian/" "/.vagrant/" "/release/" "/debug/" "/build/" ) include(CPack) diff --git a/cmake/InstallConfig.cmake b/cmake/InstallConfig.cmake deleted file mode 100644 index a1a50dc19..000000000 --- a/cmake/InstallConfig.cmake +++ /dev/null @@ -1,25 +0,0 @@ -function(install_if_not_exists src dest) - if(NOT IS_ABSOLUTE "${src}") - set(src "${CMAKE_CURRENT_SOURCE_DIR}/${src}") - endif() - get_filename_component(src_name "${src}" NAME) - if (NOT IS_ABSOLUTE "${dest}") - set(dest "${CMAKE_INSTALL_PREFIX}/${dest}") - endif() - install(CODE " - if(NOT EXISTS \"\$ENV{DESTDIR}${dest}/${src_name}\") - #file(INSTALL \"${src}\" DESTINATION \"${dest}\") - message(STATUS \"Installing: \$ENV{DESTDIR}${dest}/${src_name}\") - execute_process(COMMAND \${CMAKE_COMMAND} -E copy \"${src}\" - \"\$ENV{DESTDIR}${dest}/${src_name}\" - RESULT_VARIABLE copy_result - ERROR_VARIABLE error_output) - if(copy_result) - message(FATAL_ERROR \${error_output}) - endif() - else() - message(STATUS \"Skipping : \$ENV{DESTDIR}${dest}/${src_name}\") - endif() - ") -endfunction(install_if_not_exists) - diff --git a/etc/CMakeLists.txt b/etc/CMakeLists.txt index 529dddb96..3fabb506e 100644 --- a/etc/CMakeLists.txt +++ b/etc/CMakeLists.txt @@ -15,60 +15,74 @@ # along with this program; if not, write to the Free Software Foundation # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -include(InstallConfig) - configure_file(icinga/icinga-classic-apache.conf.cmake ${CMAKE_CURRENT_BINARY_DIR}/icinga/icinga-classic-apache.conf) -install_if_not_exists(icinga2/icinga2.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2) -install_if_not_exists(icinga2/constants.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2) -install_if_not_exists(icinga2/conf.d/commands.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d) -install_if_not_exists(icinga2/conf.d/downtimes.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d) -install_if_not_exists(icinga2/conf.d/generic-host.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d) -install_if_not_exists(icinga2/conf.d/generic-service.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d) -install_if_not_exists(icinga2/conf.d/generic-user.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d) -install_if_not_exists(icinga2/conf.d/groups.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d) -install_if_not_exists(icinga2/conf.d/hosts/localhost.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts) -install_if_not_exists(icinga2/conf.d/hosts/localhost/disk.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts/localhost) -install_if_not_exists(icinga2/conf.d/hosts/localhost/http.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts/localhost) -install_if_not_exists(icinga2/conf.d/hosts/localhost/icinga.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts/localhost) -install_if_not_exists(icinga2/conf.d/hosts/localhost/kernel.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts/localhost) -install_if_not_exists(icinga2/conf.d/hosts/localhost/load.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts/localhost) -install_if_not_exists(icinga2/conf.d/hosts/localhost/processes.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts/localhost) -install_if_not_exists(icinga2/conf.d/hosts/localhost/ssh.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts/localhost) -install_if_not_exists(icinga2/conf.d/hosts/localhost/swap.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts/localhost) -install_if_not_exists(icinga2/conf.d/hosts/localhost/users.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts/localhost) -install_if_not_exists(icinga2/conf.d/notifications.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d) -install_if_not_exists(icinga2/conf.d/timeperiods.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d) -install_if_not_exists(icinga2/conf.d/users.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d) -install_if_not_exists(icinga2/features-available/agent.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/checker.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/command.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/compatlog.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/debuglog.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/graphite.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/ido-mysql.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/ido-pgsql.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/livestatus.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/mainlog.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/notification.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/perfdata.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/statusdata.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/features-available/syslog.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available) -install_if_not_exists(icinga2/scripts/check_kernel ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/scripts) -install_if_not_exists(icinga2/scripts/mail-host-notification.sh ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/scripts) -install_if_not_exists(icinga2/scripts/mail-service-notification.sh ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/scripts) -install_if_not_exists(logrotate.d/icinga2 ${CMAKE_INSTALL_SYSCONFDIR}/logrotate.d) +install( + FILES icinga2/icinga2.conf icinga2/constants.conf + DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/icinga2 +) -install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_SYSCONFDIR}/icinga2/features-enabled\")") -install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink ../features-available/checker.conf \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_SYSCONFDIR}/icinga2/features-enabled/checker.conf\")") -install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink ../features-available/notification.conf \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_SYSCONFDIR}/icinga2/features-enabled/notification.conf\")") -install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink ../features-available/mainlog.conf \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_SYSCONFDIR}/icinga2/features-enabled/mainlog.conf\")") +install( + FILES icinga2/conf.d/commands.conf icinga2/conf.d/downtimes.conf icinga2/conf.d/generic-host.conf + icinga2/conf.d/generic-service.conf icinga2/conf.d/generic-user.conf icinga2/conf.d/groups.conf + icinga2/conf.d/notifications.conf icinga2/conf.d/timeperiods.conf icinga2/conf.d/users.conf + DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d +) + +install( + FILES icinga2/conf.d/hosts/localhost.conf + DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts +) + +install( + FILES icinga2/conf.d/hosts/localhost/disk.conf icinga2/conf.d/hosts/localhost/http.conf + icinga2/conf.d/hosts/localhost/icinga.conf icinga2/conf.d/hosts/localhost/kernel.conf + icinga2/conf.d/hosts/localhost/load.conf icinga2/conf.d/hosts/localhost/processes.conf + icinga2/conf.d/hosts/localhost/ssh.conf icinga2/conf.d/hosts/localhost/swap.conf + icinga2/conf.d/hosts/localhost/users.conf + DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/conf.d/hosts/localhost +) + +install( + FILES icinga2/features-available/agent.conf icinga2/features-available/checker.conf + icinga2/features-available/command.conf icinga2/features-available/compatlog.conf + icinga2/features-available/debuglog.conf icinga2/features-available/graphite.conf + icinga2/features-available/ido-mysql.conf icinga2/features-available/ido-pgsql.conf + icinga2/features-available/livestatus.conf icinga2/features-available/mainlog.conf + icinga2/features-available/notification.conf icinga2/features-available/perfdata.conf + icinga2/features-available/statusdata.conf icinga2/features-available/syslog.conf + DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available +) + +install( + FILES icinga2/scripts/check_kernel icinga2/scripts/mail-host-notification.sh + icinga2/scripts/mail-service-notification.sh + DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/scripts +) + +install( + FILES logrotate.d/icinga2 + DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/logrotate.d +) + +if(NOT WIN32) + install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_SYSCONFDIR}/icinga2/features-enabled\")") + install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink ../features-available/checker.conf \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_SYSCONFDIR}/icinga2/features-enabled/checker.conf\")") + install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink ../features-available/notification.conf \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_SYSCONFDIR}/icinga2/features-enabled/notification.conf\")") + install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink ../features-available/mainlog.conf \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_SYSCONFDIR}/icinga2/features-enabled/mainlog.conf\")") +else() + install( + FILES icinga2/features-enabled/checker.conf icinga2/features-enabled/notification.conf + icinga2/features-enabled/mainlog.conf + DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-enabled + ) +endif() if(NOT WIN32) configure_file(init.d/icinga2.cmake ${CMAKE_CURRENT_BINARY_DIR}/init.d/icinga2) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/init.d/icinga2 - DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/init.d + DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/init.d PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) endif() diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 72e36a16c..2a08b32d1 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -417,16 +417,7 @@ int Main(void) #ifdef _WIN32 static int SetupService(bool install, int argc, char **argv) { - SC_HANDLE schSCManager; - SC_HANDLE schService; - TCHAR szPath[MAX_PATH * 5]; - - if (!GetModuleFileName(NULL, szPath, MAX_PATH)) { - printf("Cannot install service (%d)\n", GetLastError()); - return 1; - } - - schSCManager = OpenSCManager( + SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS); @@ -436,15 +427,20 @@ static int SetupService(bool install, int argc, char **argv) return 1; } - strcat(szPath, " --scm"); + TCHAR szPath[MAX_PATH]; - for (int i = 0; i < argc; i++) { - strcat(szPath, " \""); - strcat(szPath, argv[i]); - strcat(szPath, "\""); + if (!GetModuleFileName(NULL, szPath, MAX_PATH)) { + printf("Cannot install service (%d)\n", GetLastError()); + return 1; } - schService = OpenService(schSCManager, "icinga2", DELETE); + String szArgs; + szArgs = Utility::EscapeShellArg(szPath) + " --scm"; + + for (int i = 0; i < argc; i++) + szArgs += " " + Utility::EscapeShellArg(argv[i]); + + SC_HANDLE schService = OpenService(schSCManager, "icinga2", DELETE); if (schService != NULL) { if (!DeleteService(schService)) { @@ -469,7 +465,7 @@ static int SetupService(bool install, int argc, char **argv) SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, - szPath, + szArgs.CStr(), NULL, NULL, NULL, diff --git a/lib/base/tlsutility.cpp b/lib/base/tlsutility.cpp index 56ae17394..4d17a1e72 100644 --- a/lib/base/tlsutility.cpp +++ b/lib/base/tlsutility.cpp @@ -201,6 +201,44 @@ shared_ptr GetX509Certificate(const String& pemfile) return shared_ptr(cert, X509_free); } +int MakeX509CSR(const char *cn, const char *keyfile, const char *csrfile) +{ + InitializeOpenSSL(); + + RSA *rsa = RSA_generate_key(4096, RSA_F4, NULL, NULL); + + BIO *bio = BIO_new(BIO_s_file()); + BIO_write_filename(bio, const_cast(keyfile)); + PEM_write_bio_RSAPrivateKey(bio, rsa, NULL, NULL, 0, NULL, NULL); + BIO_free(bio); + + X509_REQ *req = X509_REQ_new(); + + if (!req) + return 0; + + EVP_PKEY *key = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(key, rsa); + X509_REQ_set_version(req, 0); + X509_REQ_set_pubkey(req, key); + + X509_NAME *name = X509_REQ_get_subject_name(req); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)cn, -1, -1, 0); + + X509_REQ_sign(req, key, EVP_sha1()); + + EVP_PKEY_free(key); + + bio = BIO_new(BIO_s_file()); + BIO_write_filename(bio, const_cast(csrfile)); + PEM_write_bio_X509_REQ(bio, req); + BIO_free(bio); + + X509_REQ_free(req); + + return 1; +} + String SHA256(const String& s) { SHA256_CTX context; diff --git a/lib/base/tlsutility.h b/lib/base/tlsutility.h index d006d94b8..8dcfdb154 100644 --- a/lib/base/tlsutility.h +++ b/lib/base/tlsutility.h @@ -37,6 +37,7 @@ shared_ptr I2_BASE_API MakeSSLContext(const String& pubkey, const Strin 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); +extern "C" int I2_BASE_API MakeX509CSR(const char *cn, const char *keyfile, const char *csrfile); String I2_BASE_API SHA256(const String& s); class I2_BASE_API openssl_error : virtual public std::exception, virtual public boost::exception { }; diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index b1cf6ecea..9cf043ec2 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -772,6 +772,37 @@ String Utility::EscapeShellCmd(const String& s) return result; } +String Utility::EscapeShellArg(const String& s) +{ + String result; + +#ifdef _WIN32 + result = "\""; +#else /* _WIN32 */ + result = "'"; +#endif /* _WIN32 */ + + BOOST_FOREACH(char ch, s) { +#ifdef _WIN32 + if (ch == '"' || ch == '%') { + result += ' '; + } +#else /* _WIN32 */ + if (ch == '\') { + result += "'\\'"; +#endif + result += ch; + } + +#ifdef _WIN32 + result += '"'; +#else /* _WIN32 */ + result += '\''; +#endif /* _WIN32 */ + + return result; +} + #ifdef _WIN32 static void WindowsSetThreadName(const char *name) { diff --git a/lib/base/utility.h b/lib/base/utility.h index dbea5a6f2..10f7633d3 100644 --- a/lib/base/utility.h +++ b/lib/base/utility.h @@ -101,6 +101,7 @@ public: static void SetNonBlockingSocket(SOCKET s); static String EscapeShellCmd(const String& s); + static String EscapeShellArg(const String& s); static void SetThreadName(const String& name, bool os = true); static String GetThreadName(void); diff --git a/lib/methods/pluginchecktask.cpp b/lib/methods/pluginchecktask.cpp index 3b87faa5f..05f9cded3 100644 --- a/lib/methods/pluginchecktask.cpp +++ b/lib/methods/pluginchecktask.cpp @@ -51,7 +51,7 @@ void PluginCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckRes resolvers.push_back(std::make_pair("command", commandObj)); resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance())); - Value command = MacroProcessor::ResolveMacros(raw_command, resolvers, checkable->GetLastCheckResult(), Utility::EscapeShellCmd); + Value command = MacroProcessor::ResolveMacros(raw_command, resolvers, checkable->GetLastCheckResult(), Utility::EscapeShellArg); Dictionary::Ptr envMacros = make_shared(); diff --git a/lib/methods/plugineventtask.cpp b/lib/methods/plugineventtask.cpp index 8522956a4..6ff612ba6 100644 --- a/lib/methods/plugineventtask.cpp +++ b/lib/methods/plugineventtask.cpp @@ -48,7 +48,7 @@ void PluginEventTask::ScriptFunc(const Checkable::Ptr& checkable) resolvers.push_back(std::make_pair("command", commandObj)); resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance())); - Value command = MacroProcessor::ResolveMacros(raw_command, resolvers, checkable->GetLastCheckResult(), Utility::EscapeShellCmd); + Value command = MacroProcessor::ResolveMacros(raw_command, resolvers, checkable->GetLastCheckResult(), Utility::EscapeShellArg); Dictionary::Ptr envMacros = make_shared(); diff --git a/lib/methods/pluginnotificationtask.cpp b/lib/methods/pluginnotificationtask.cpp index 1f69d6b1a..06055b8b5 100644 --- a/lib/methods/pluginnotificationtask.cpp +++ b/lib/methods/pluginnotificationtask.cpp @@ -63,7 +63,7 @@ void PluginNotificationTask::ScriptFunc(const Notification::Ptr& notification, c resolvers.push_back(std::make_pair("command", commandObj)); resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance())); - Value command = MacroProcessor::ResolveMacros(raw_command, resolvers, cr, Utility::EscapeShellCmd); + Value command = MacroProcessor::ResolveMacros(raw_command, resolvers, cr, Utility::EscapeShellArg); Dictionary::Ptr envMacros = make_shared();