308 lines
11 KiB
C++
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
|
|
|