Sleds/libeye/eyelog.h

308 lines
11 KiB
C++

// Copyright (c) 2014-2015 IONU Security, Inc. All rights reserved.
//
// Logging and auditing services
#ifndef eyelog_h
#define eyelog_h
#include <stdarg.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#if defined(__APPLE__)
#include <asl.h>
#endif
#include "eyering.h"
#ifdef WIN32
# ifdef DLLEXPORT
# define LIBEYE_DLL __declspec(dllexport)
# else
# define LIBEYE_DLL __declspec(dllimport)
# endif
#else
#define LIBEYE_DLL
#endif
// Linux and OSX use syslog
#if defined (LIN64) || defined (Darwin) || defined (__MACH__)
#define LOG_TO_SYSLOG
#endif
#define IONULOG sequencelogic::LogWrapper
#if (defined(ANDROID) || defined(DEBUG) || (defined(WIN32) && defined(_DEBUG)))
#define IONUDEBUG(...) IONULOG (EyeLog::IONU_DEBUG, __VA_ARGS__)
#define IONUTRACE(...) IONULOG (EyeLog::IONU_TRACE, __VA_ARGS__)
#else
#define IONUDEBUG(...)
#define IONUTRACE(...)
#endif
#define IONUFATAL(...) IONULOG (EyeLog::IONU_FATAL, __VA_ARGS__)
#define IONUERROR(...) IONULOG (EyeLog::IONU_ERROR, __VA_ARGS__)
#define IONUWARN(...) IONULOG (EyeLog::IONU_WARN, __VA_ARGS__)
#define IONUINFO(...) IONULOG (EyeLog::IONU_INFO, __VA_ARGS__)
#define IONUAUDIT(code,...) sequencelogic::AuditWrapper (code, __VA_ARGS__)
#define IONUCONFIGLOG EyeLog::GetInstance()->ConfigLogger
#define IONUCONFIGFILELOG EyeLog::GetInstance()->ConfigFileLogger
#define IONUCLOSELOG EyeLog::GetInstance()->CloseLogger
#define IONUBEGINAUDIT EyeLog::GetInstance()->BeginAudit
#define IONU_AUDIT_CODES \
X (AUDIT_START, 0, AuditStart) \
X (ACCOUNT_CHANGE, 1, AccountChange) \
X (ACCOUNT_CONTACT, 2, AccountContact) \
X (ACCOUNT_CREATE, 3, AccountCreate) \
X (ACCOUNT_DELETE, 4, AccountDelete) \
X (ACCOUNT_LOCKOUT, 5, AccountLockout) \
X (ACCOUNT_LOGIN, 6, AccountLogin) \
X (ACCOUNT_LOGOUT, 7, AccountLogout) \
X (ACCOUNT_PASSWORD, 8, AccountPassword) \
X (CONNECT_VPN, 10, ConnectVPN) \
X (CONNECT_SSL, 11, ConnectSSL) \
X (CONNECT_PROXY, 12, ConnectProxy) \
X (CONNECT_RELAY, 13, ConnectRelay) \
X (DEVICE_DELETE, 20, DeviceDelete) \
X (DEVICE_PROVISION, 21, DeviceProvision) \
X (DEVICE_RESET, 22, DeviceReset) \
X (DEVICE_WIPE, 23, DeviceWipe) \
X (DOCUMENT_ACCESS, 30, DocumentAccess) \
X (DOCUMENT_ADD, 31, DocumentAdd) \
X (DOCUMENT_DELETE, 32, DocumentDelete) \
X (DOCUMENT_DOWNLOAD, 33, DocumentDownload) \
X (DOCUMENT_EXPORT, 34, DocumentExport) \
X (DOCUMENT_IMPORT, 35, DocumentImport) \
X (DOCUMENT_MODIFY, 36, DocumentModify) \
X (DOCUMENT_RECEIVE, 37, DocumentReceive) \
X (DOCUMENT_SEND, 38, DocumentSend) \
X (DOCUMENT_UPLOAD, 39, DocumentUpload) \
X (GROUP_CREATE, 40, GroupCreate) \
X (GROUP_DELETE, 41, GroupDelete) \
X (GROUP_MODIFY, 42, GroupUpdate) \
X (POLICY_CHANGE, 50, PolicyChange) \
X (STORAGE_BACKUP, 60, StorageBackup) \
X (STORAGE_LISTING, 61, StorageListing) \
X (STORAGE_RESTORE, 62, StorageRestore) \
// Defaults
#define IONU_MAX_LOG_FILES 3
#define IONU_MAX_LOG_FILE_SIZE (1024*1024) // 1MB
#define IONU_MAX_AUDIT_ERRORS 10
namespace sequencelogic {
class EyeLog {
public:
enum LOG_LEVEL {
IONU_AUDIT = 0, // Lowest level, audit messages can never be suppressed
IONU_FATAL = 1, // Severe errors that cause the app to terminate
IONU_ERROR = 2, // Runtime errors reported to user
IONU_WARN = 3, // Runtime warnings optionally reported to user
IONU_INFO = 4, // Interesting runtime events that the user may choose to see
IONU_DEBUG = 5, // Debug information for developers, not in production code
IONU_TRACE = 6 // More detailed information for developers
};
enum LOG_SINK {
IONU_SYSLOG, // uses platform specific system logging facility
IONU_CONSOLE, // stdout
IONU_FILE // file based log
//IONU_NETWORK // network based log
};
enum LOG_FORMAT {
IONU_LEVEL, // %l Error, Warn, Debug
IONU_ULEVEL, // %L ERROR, WARN, DEBUG
IONU_CLIENT, // %c client identifier
IONU_ETIME, // %e milliseconds elapsed time
IONU_TIME, // %t time
IONU_MESSAGE, // %m log message
IONU_TERMINAL // end
};
enum AUDIT_CODE {
#define X(code,value,description) \
code = value,
IONU_AUDIT_CODES
#undef X
};
LIBEYE_DLL static EyeLog* GetInstance ();
/**
* Configure logging settings
* @param client identifier
* @param device identifier
* @param level to log
* @param sink to console, file, syslog...
* @param format string to use for messages
* @return true for success
*/
LIBEYE_DLL bool ConfigLogger (const std::string& client, const std::string& device,
LOG_LEVEL level, LOG_SINK sink = IONU_CONSOLE, const std::string& format = "");
/**
* Configure logging settings for file based logging
* @param client identifier
* @param device identifier
* @param level to log
* @param file to log to
* @param sink to console, file, syslog...
* @param format string to use for messages
* @return true for success
*/
LIBEYE_DLL bool ConfigFileLogger (const char* client, const char* device,
LOG_LEVEL level, const char* logfile, LOG_SINK sink = IONU_FILE, const char* format = "");
LIBEYE_DLL bool ConfigFileLogger (const std::string& client, const std::string& device,
LOG_LEVEL level, const std::string& logfile, LOG_SINK sink = IONU_FILE, const std::string& format = "");
LIBEYE_DLL bool CloseLogger (void);
LIBEYE_DLL bool CloseLogger (const std::string& logFile);
void SetMaxLogFile (size_t bytes) { maxLogFileSize = bytes; } // Maximum size before we roll over to a new file
void SetLogFiles (int files) { if (files > 1 && files < 100) maxLogFiles = files; } // Maximum number of logfiles to keep
void SetLogLevel (LOG_LEVEL level) { logLevel = level; }
// Client side methods
/**
* Start a new audit log
* @param auditor public key
* @param cache directory
* @param callback to upload audit logs to server
*/
LIBEYE_DLL bool BeginAudit (const Key& auditorPublicKey, const std::string& auditCacheDir /*, uploadcallback() */);
LIBEYE_DLL bool BeginAudit (const std::string& auditorPublicKey, const std::string& auditCacheDir /*, uploadcallback() */);
/**
* Log a message
* @param level to log
* @param msg to log
* @return true for success
*/
LIBEYE_DLL bool Log (LOG_LEVEL level, std::string& msg);
/**
* Log an audit message
* @param code to log
* @param msg to log
* @return true for success
*/
LIBEYE_DLL bool Audit (AUDIT_CODE code, std::string& msg);
// Server side methods
LIBEYE_DLL bool ReviewAudit (const Key& auditorPrivateKey, const std::string& auditFile);
LIBEYE_DLL bool ReviewAudit (const std::string& auditorPrivateKey, const std::string& auditFile);
LIBEYE_DLL bool ConsolidateAudit (const Key& auditorPrivateKey, const std::string& auditFile1, const std::string& auditFile2);
protected:
EyeLog ();
~EyeLog();
private:
static EyeLog* _instance; // Singleton
long long startTime; // Log creation time in mS for elapsed time (%e) format
std::string clientId; // Short identfier, per message: "cgws", "sgws", "im", etc. for system and audit logs
std::string deviceId; // Long identifier, per log file: device URN, device type (ipad/iphone), build #, etc.
// Client control over logging
LOG_LEVEL logLevel; // all log output (but not audit) omitted when > this level
LOG_SINK localSink; // local device log sink
LOG_FORMAT formatargs[6]; // arguments for log message format string
std::string format;
#ifdef WIN32
std::string sysLogFilename; // Windows has no system logger
std::fstream sysLogFile;
#endif
// Local log file variables, used when localSink == LOG_FILE
LOG_LEVEL logFileLevel; // all log output (but not audit) omitted when > this level
std::string logFilename; // Base filename for LOG_FILE logging
std::ofstream logFile; // Current logfile
size_t maxLogFileSize; // Maximum size before we roll over to a new file
int maxLogFiles; // maximum number of logfiles to keep
size_t logFileSize; // Current logfile size
// Auditing variables
int auditId; // Audit message sequence number
std::vector<std::string> ids; // Usually just one client id, audit files may have multiple
std::string auditCachePath; // local filesystem path for batch/caching of audit data
std::fstream auditFile; // current audit cache file
std::vector<std::string> queue; // Queue of audit messages for verification
Keyring* auditKeyring; // Public and/or private key plus AESHMAC key for encrypting this session
Key* auditKey; // AESHMAC key
#ifdef __APPLE__
aslclient aslClientHandle; // Apple system logger handle
#endif
void ProcessFormat (const std::string& fmt);
const char* AuditCodeString (int auditcode);
bool GetAuditKey (const Key& pk, const std::string& auditFilename);
#ifdef LOG_TO_SYSLOG
void SafeSyslog (int priority, std::string msg);
#endif
};
void logsprintf(std::string& msg, const char *s);
#ifdef WIN32
// VS 2012 does not support variadic templates so use old dangerous va style code
#define LOG_USE_VA_STYLE
#endif
#ifdef LOG_USE_VA_STYLE
// VS 2012 does not support variadic templates so use old dangerous va style code
#include <stdarg.h>
void logvasprintf (std::string& msg, const char *fmt, va_list args);
void logsprintf (std::string& msg, const char *fmt, ...);
LIBEYE_DLL void LogWrapper (EyeLog::LOG_LEVEL level, const char *s, ...);
LIBEYE_DLL void AuditWrapper (EyeLog::AUDIT_CODE code, const char *s, ...);
#else
template<typename T, typename... Args>
void logsprintf(std::string& msg, const char *s, T value, Args... args)
{
while (*s) {
if (*s == '%' && *++s != '%') {
std::stringstream stream;
stream << value;
msg += stream.str();
if (*s)
logsprintf(msg, s + 1, args...); // peel of first argument
return;
}
msg += *s++;
}
// Ignore extra arguments
//printf ("extra arguments provided to EyeLog::Log\n");
}
template<typename... Args>
void LogWrapper (EyeLog::LOG_LEVEL level, const char *s, Args... args)
{
if (s == NULL) return;
std::string msg = "";
logsprintf (msg, s, args...);
EyeLog::GetInstance()->Log (level, msg);
}
template<typename... Args>
void AuditWrapper (EyeLog::AUDIT_CODE code, const char *s, Args... args)
{
if (s == NULL) return;
std::string msg = "";
logsprintf (msg, s, args...);
EyeLog::GetInstance()->Audit (code, msg);
}
#endif
} //namespace sequencelogic
#endif