182 lines
3.2 KiB
C++
182 lines
3.2 KiB
C++
/*
|
|
* This is an auditd plugin for sending auditd data
|
|
* to clickhouse DB.
|
|
* Copyright (C) 2020 Aleksei Nikiforov <darktemplar@basealt.ru>
|
|
*
|
|
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "logging.hpp"
|
|
|
|
#include <time.h>
|
|
|
|
#include <boost/scope_exit.hpp>
|
|
|
|
std::mutex Logger::s_mutex;
|
|
|
|
Logger::Logger()
|
|
: m_initialized(false)
|
|
{
|
|
}
|
|
|
|
Logger::~Logger()
|
|
{
|
|
dump_impl();
|
|
}
|
|
|
|
Logger& Logger::instance()
|
|
{
|
|
static Logger s_instance;
|
|
return s_instance;
|
|
}
|
|
|
|
void Logger::open(const char *filename)
|
|
{
|
|
std::lock_guard<std::mutex> lock(s_mutex);
|
|
instance().open_impl(filename);
|
|
}
|
|
|
|
void Logger::initialize()
|
|
{
|
|
std::lock_guard<std::mutex> lock(s_mutex);
|
|
instance().initialize_impl();
|
|
}
|
|
|
|
void Logger::write(const char *format, ...)
|
|
{
|
|
std::lock_guard<std::mutex> lock(s_mutex);
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
instance().write_impl(format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
void Logger::dump()
|
|
{
|
|
std::lock_guard<std::mutex> lock(s_mutex);
|
|
instance().dump_impl();
|
|
}
|
|
|
|
void Logger::open_impl(const char *filename)
|
|
{
|
|
m_logfile_name = filename;
|
|
|
|
initialize_impl();
|
|
}
|
|
|
|
void Logger::initialize_impl()
|
|
{
|
|
m_initialized = true;
|
|
}
|
|
|
|
void Logger::write_impl(const char *format, va_list args)
|
|
{
|
|
FILE *outfile = NULL;
|
|
|
|
std::string datestring = getdatestring();
|
|
|
|
if (!m_logfile_name.empty())
|
|
{
|
|
outfile = fopen(m_logfile_name.c_str(), "at");
|
|
}
|
|
|
|
if (outfile != NULL)
|
|
{
|
|
fprintf(outfile, "%s: ", datestring.c_str());
|
|
vfprintf(outfile, format, args);
|
|
fprintf(outfile, "\n");
|
|
|
|
fclose(outfile);
|
|
}
|
|
else
|
|
{
|
|
// save logged data for later use
|
|
char *data = NULL;
|
|
|
|
BOOST_SCOPE_EXIT(&data)
|
|
{
|
|
if (data != NULL)
|
|
{
|
|
free(data);
|
|
}
|
|
} BOOST_SCOPE_EXIT_END;
|
|
|
|
int result = vasprintf(&data, format, args);
|
|
|
|
if ((result >= 0) && (data != NULL))
|
|
{
|
|
m_lines.push_back(std::make_pair(datestring,data));
|
|
}
|
|
|
|
if (m_initialized)
|
|
{
|
|
dump_impl();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Logger::dump_impl()
|
|
{
|
|
FILE *outfile = NULL;
|
|
|
|
if (!m_logfile_name.empty())
|
|
{
|
|
outfile = fopen(m_logfile_name.c_str(), "at");
|
|
}
|
|
|
|
for (auto iter = m_lines.begin(); iter != m_lines.end(); ++iter)
|
|
{
|
|
fprintf((outfile != NULL) ? outfile : stderr, "%s: %s\n", iter->first.c_str(), iter->second.c_str());
|
|
}
|
|
|
|
if (outfile != NULL)
|
|
{
|
|
fclose(outfile);
|
|
}
|
|
else
|
|
{
|
|
fflush(stderr);
|
|
}
|
|
|
|
m_lines.clear();
|
|
}
|
|
|
|
std::string Logger::getdatestring() const
|
|
{
|
|
std::string result;
|
|
|
|
time_t t = time(nullptr);
|
|
struct tm tm_inst;
|
|
|
|
auto tm_ptr = localtime_r(&t, &tm_inst);
|
|
|
|
if (tm_ptr != nullptr)
|
|
{
|
|
char buffer[4096];
|
|
|
|
auto buffer_res = strftime(buffer, sizeof(buffer) - 1, "%c %Z", tm_ptr);
|
|
if (buffer_res > 0)
|
|
{
|
|
buffer[buffer_res] = 0;
|
|
|
|
result = buffer;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|