2012-05-10 12:06:41 +02:00
|
|
|
/******************************************************************************
|
|
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
|
|
******************************************************************************/
|
|
|
|
|
2012-04-22 16:45:31 +02:00
|
|
|
#include "i2-base.h"
|
2012-05-09 10:15:51 +02:00
|
|
|
#include <mmatch.h>
|
2012-04-22 16:45:31 +02:00
|
|
|
|
|
|
|
using namespace icinga;
|
|
|
|
|
2012-04-24 14:02:15 +02:00
|
|
|
bool I2_EXPORT Utility::m_SSLInitialized = false;
|
|
|
|
|
2012-04-22 16:45:31 +02:00
|
|
|
/**
|
|
|
|
* Daemonize
|
|
|
|
*
|
|
|
|
* Detaches from the controlling terminal.
|
|
|
|
*/
|
|
|
|
void Utility::Daemonize(void) {
|
|
|
|
#ifndef _WIN32
|
|
|
|
pid_t pid;
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
pid = fork();
|
2012-04-23 08:42:24 +02:00
|
|
|
if (pid < 0)
|
|
|
|
throw PosixException("fork failed", errno);
|
2012-04-22 16:45:31 +02:00
|
|
|
|
|
|
|
if (pid)
|
|
|
|
exit(0);
|
|
|
|
|
|
|
|
fd = open("/dev/null", O_RDWR);
|
2012-04-23 08:42:24 +02:00
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
throw PosixException("open failed", errno);
|
|
|
|
|
|
|
|
if (fd != 0)
|
|
|
|
dup2(fd, 0);
|
|
|
|
|
|
|
|
if (fd != 1)
|
|
|
|
dup2(fd, 1);
|
|
|
|
|
|
|
|
if (fd != 2)
|
|
|
|
dup2(fd, 2);
|
|
|
|
|
|
|
|
if (fd > 2)
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
if (setsid() < 0)
|
|
|
|
throw PosixException("setsid failed", errno);
|
2012-04-22 16:45:31 +02:00
|
|
|
#endif
|
|
|
|
}
|
2012-04-24 14:02:15 +02:00
|
|
|
|
2012-05-08 15:14:20 +02:00
|
|
|
/**
|
|
|
|
* InitializeOpenSSL
|
|
|
|
*
|
|
|
|
* Initializes the OpenSSL library.
|
|
|
|
*/
|
2012-04-24 14:02:15 +02:00
|
|
|
void Utility::InitializeOpenSSL(void)
|
|
|
|
{
|
|
|
|
if (!m_SSLInitialized) {
|
|
|
|
SSL_library_init();
|
|
|
|
SSL_load_error_strings();
|
|
|
|
|
|
|
|
m_SSLInitialized = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-08 15:14:20 +02:00
|
|
|
/**
|
|
|
|
* MakeSSLContext
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2012-04-24 14:02:15 +02:00
|
|
|
shared_ptr<SSL_CTX> Utility::MakeSSLContext(string pubkey, string privkey, string cakey)
|
|
|
|
{
|
|
|
|
InitializeOpenSSL();
|
|
|
|
|
|
|
|
SSL_METHOD *sslMethod = (SSL_METHOD *)TLSv1_method();
|
|
|
|
|
|
|
|
shared_ptr<SSL_CTX> sslContext = shared_ptr<SSL_CTX>(SSL_CTX_new(sslMethod), 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.c_str()))
|
|
|
|
throw InvalidArgumentException("Could not load public X509 key file.");
|
|
|
|
|
|
|
|
if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.c_str(), SSL_FILETYPE_PEM))
|
|
|
|
throw InvalidArgumentException("Could not load private X509 key file.");
|
|
|
|
|
|
|
|
if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.c_str(), NULL))
|
|
|
|
throw InvalidArgumentException("Could not load public CA key file.");
|
|
|
|
|
|
|
|
return sslContext;
|
|
|
|
}
|
2012-04-24 15:56:48 +02:00
|
|
|
|
2012-05-08 15:14:20 +02:00
|
|
|
/**
|
|
|
|
* GetCertificateCN
|
|
|
|
*
|
|
|
|
* Retrieves the common name for a X509 certificate.
|
|
|
|
*
|
|
|
|
* @param certificate The X509 certificate.
|
|
|
|
* @returns The common name.
|
|
|
|
*/
|
2012-04-24 15:56:48 +02:00
|
|
|
string Utility::GetCertificateCN(const shared_ptr<X509>& 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)
|
|
|
|
throw InvalidArgumentException("X509 certificate has no CN attribute.");
|
|
|
|
|
|
|
|
return buffer;
|
|
|
|
}
|
2012-04-27 11:44:34 +02:00
|
|
|
|
2012-05-08 15:14:20 +02:00
|
|
|
/**
|
|
|
|
* GetX509Certificate
|
|
|
|
*
|
|
|
|
* Retrieves an X509 certificate from the specified file.
|
|
|
|
*
|
|
|
|
* @param pemfile The filename.
|
|
|
|
* @returns An X509 certificate.
|
|
|
|
*/
|
2012-04-27 11:44:34 +02:00
|
|
|
shared_ptr<X509> Utility::GetX509Certificate(string pemfile)
|
|
|
|
{
|
|
|
|
X509 *cert;
|
|
|
|
BIO *fpcert = BIO_new(BIO_s_file());
|
|
|
|
|
|
|
|
if (fpcert == NULL)
|
|
|
|
throw OpenSSLException("BIO_new failed", ERR_get_error());
|
|
|
|
|
|
|
|
if (BIO_read_filename(fpcert, pemfile.c_str()) < 0)
|
|
|
|
throw OpenSSLException("BIO_read_filename failed", ERR_get_error());
|
|
|
|
|
|
|
|
cert = PEM_read_bio_X509_AUX(fpcert, NULL, NULL, NULL);
|
|
|
|
if (cert == NULL)
|
|
|
|
throw OpenSSLException("PEM_read_bio_X509_AUX failed", ERR_get_error());
|
|
|
|
|
|
|
|
BIO_free(fpcert);
|
|
|
|
|
|
|
|
return shared_ptr<X509>(cert, X509_free);
|
|
|
|
}
|
2012-05-09 10:15:51 +02:00
|
|
|
|
|
|
|
bool Utility::Match(string pattern, string text)
|
|
|
|
{
|
2012-05-09 12:24:47 +02:00
|
|
|
return (match(pattern.c_str(), text.c_str()) == 0);
|
2012-05-09 10:15:51 +02:00
|
|
|
}
|