ccaudit_extensions.cpp [plain text]
#include <errno.h>
#include <assert.h>
#include <stdio.h> // vsnprintf()
#include <stdarg.h> // va_start(), et al.
#include <syslog.h>
#include <string.h> // memcpy()
#include <bsm/audit_uevents.h> // AUE_ssauth*
#include <bsm/libbsm.h>
#include <security_utilities/errors.h>
#include <security_utilities/ccaudit.h>
#include "ccaudit_extensions.h"
namespace Security
{
namespace CommonCriteria
{
namespace Securityd
{
AuditLogger::AuditLogger(const audit_token_t *srcToken, short auEvent)
: mAuditFd(-1), mEvent(auEvent), mClientInfoSet(false)
{
setClientInfo(srcToken);
}
AuditLogger::AuditLogger(const AuditToken &srcToken, short auEvent)
: mAuditFd(-1), mEvent(auEvent), mClientInfoSet(false)
{
setClientInfo(srcToken);
}
AuditLogger::~AuditLogger()
{
close();
}
bool
AuditLogger::open()
{
if (-1 != mAuditFd)
return true;
int acond = au_get_state();
switch (acond)
{
case AUC_NOAUDIT:
return false;
case AUC_AUDITING:
break;
default:
logInternalError("error checking auditing status (%d)", acond);
UnixError::throwMe(acond); }
if ((mAuditFd = au_open()) < 0)
{
logInternalError("au_open() failed (%s)", strerror(errno));
UnixError::throwMe(errno);
}
return true;
}
void
AuditLogger::close(bool writeLog)
{
if (-1 != mAuditFd)
{
int keep = writeLog == true ? AU_TO_WRITE : AU_TO_NO_WRITE;
int error = au_close(mAuditFd, keep, mEvent);
mAuditFd = -1;
if (writeLog == true && error < 0)
{
logInternalError("au_close() failed; record not committed");
UnixError::throwMe(error);
}
}
}
void
AuditLogger::setClientInfo(const audit_token_t *srcToken)
{
assert(srcToken);
audit_token_to_au32(*srcToken, &mAuditId, &mEuid, &mEgid, &mRuid, &mRgid, &mPid, &mAuditSessionId, &mOldTerminalId);
mTerminalId.at_type = AU_IPv4;
mTerminalId.at_addr[0] = mOldTerminalId.machine;
mTerminalId.at_port = mOldTerminalId.port;
mClientInfoSet = true;
}
void
AuditLogger::setClientInfo(const AuditToken &srcToken)
{
mAuditId = srcToken.auditId();
mEuid = srcToken.euid();
mEgid = srcToken.egid();
mRuid = srcToken.ruid();
mRgid = srcToken.rgid();
mPid = srcToken.pid();
mAuditSessionId = srcToken.sessionId();
memcpy(&mOldTerminalId, &(srcToken.terminalId()), sizeof(mOldTerminalId));
mTerminalId.at_type = AU_IPv4;
mTerminalId.at_addr[0] = mOldTerminalId.machine;
mTerminalId.at_port = mOldTerminalId.port;
mClientInfoSet = true;
}
void
AuditLogger::writeToken(token_t *token, const char *name)
{
const char *tokenName = name ? name : "<unidentified>";
if (NULL == token)
{
logInternalError("Invalid '%s' token", tokenName);
close();
UnixError::throwMe(EPERM); }
if (au_write(mAuditFd, token) < 0)
{
logInternalError("Error writing '%s' token (%s)", tokenName, strerror(errno));
close();
UnixError::throwMe(errno);
}
}
void
AuditLogger::writeSubject()
{
assert(mClientInfoSet);
token_t *token;
if (AU_IPv4 == mTerminalId.at_type)
token = au_to_subject32(mAuditId, mEuid, mEgid, mRuid, mRgid, mPid, mAuditSessionId, &mOldTerminalId);
else
token = au_to_subject_ex(mAuditId, mEuid, mEgid, mRuid, mRgid, mPid, mAuditSessionId, &mTerminalId);
writeToken(token, "subject");
}
void
AuditLogger::writeReturn(char status, int reterr)
{
writeToken(au_to_return32(status, reterr), "return");
}
void
AuditLogger::logSuccess()
{
if (false == open())
return;
writeCommon();
writeReturn(0, 0);
close();
}
void
AuditLogger::logFailure(const char *errMsg, int errcode)
{
if (false == open())
return;
writeCommon();
if (errMsg)
writeToken(au_to_text(errMsg), "evaluation error");
writeReturn(EPERM, errcode);
close();
}
void
AuditLogger::logInternalError(const char *fmt, ...)
{
va_list ap;
char text[MAX_AUDITSTRING_LEN];
if (fmt != NULL)
{
int error = errno;
va_start(ap, fmt);
(void)vsnprintf(text, MAX_AUDITSTRING_LEN, fmt, ap);
va_end(ap);
syslog(LOG_AUTH | LOG_ERR, "%s", text);
errno = error;
}
}
const char *KeychainAuthLogger::sysKCAuthStr = "System keychain authorization";
const char *KeychainAuthLogger::unknownKCStr = "<unknown keychain>";
const char *KeychainAuthLogger::unknownItemStr = "<unknown item>";
KeychainAuthLogger::KeychainAuthLogger(const audit_token_t *srcToken, short auEvent)
: AuditLogger(srcToken, auEvent), mDatabase(unknownKCStr),
mItem(unknownItemStr)
{
}
KeychainAuthLogger::KeychainAuthLogger(const AuditToken &srcToken, short auEvent)
: AuditLogger(srcToken, auEvent), mDatabase(unknownKCStr),
mItem(unknownItemStr)
{
}
KeychainAuthLogger::KeychainAuthLogger(const audit_token_t *srcToken, short auEvent, const char *database, const char *item)
: AuditLogger(srcToken, auEvent)
{
setDbName(database);
setItemName(item);
}
KeychainAuthLogger::KeychainAuthLogger(const AuditToken &srcToken, short auEvent, const char *database, const char *item)
: AuditLogger(srcToken, auEvent)
{
setDbName(database);
setItemName(item);
}
void
KeychainAuthLogger::setDbName(const char *database)
{
mDatabase = database ? database : unknownKCStr;
}
void
KeychainAuthLogger::setItemName(const char *item)
{
mItem = item ? item : unknownItemStr;
}
void
KeychainAuthLogger::writeCommon()
{
writeSubject();
writeToken(au_to_text(sysKCAuthStr), sysKCAuthStr);
writeToken(au_to_text(mDatabase.c_str()), "keychain");
writeToken(au_to_text(mItem.c_str()), "keychain item");
}
const char *RightLogger::unknownRightStr = "<unknown right>";
void
RightLogger::setRight(const string &rightName)
{
mRight.clear();
mRight = rightName;
}
void
RightLogger::setRight(const char *rightName)
{
if (rightName) {
string tmpStr(rightName); setRight(tmpStr);
}
}
const char *AuthMechLogger::unknownMechStr = "<unknown mechanism>";
const char *AuthMechLogger::mechStr = "mechanism ";
AuthMechLogger::AuthMechLogger(const AuditToken &srcToken, short auEvent)
: AuditLogger(srcToken, auEvent), RightLogger(),
mEvaluatingMechanism(false), mCurrentMechanism(unknownMechStr)
{
}
AuthMechLogger::AuthMechLogger(const audit_token_t *srcToken, short auEvent)
: AuditLogger(srcToken, auEvent), RightLogger(),
mEvaluatingMechanism(false), mCurrentMechanism(unknownMechStr)
{
}
void
AuthMechLogger::setCurrentMechanism(const char *mech)
{
mCurrentMechanism.clear();
if (NULL == mech)
{
mEvaluatingMechanism = false;
}
else
{
mCurrentMechanism = mech;
mEvaluatingMechanism = true;
}
}
void
AuthMechLogger::writeCommon()
{
writeSubject();
writeToken(au_to_text(mRight.c_str()), "right");
if (true == mEvaluatingMechanism)
{
string tmpStr = mechStr; tmpStr += mCurrentMechanism;
writeToken(au_to_text(tmpStr.c_str()), "mechanism");
}
}
void
AuthMechLogger::logInterrupt(const char *msg)
{
if (false == open())
return;
writeCommon();
if (msg)
writeToken(au_to_text(msg), "interrupt");
writeReturn(0, 0);
close();
}
const char *RightAuthenticationLogger::unknownUserStr = "<unknown user>";
const char *RightAuthenticationLogger::unknownClientStr = "<unknown client>";
const char *RightAuthenticationLogger::unknownAuthCreatorStr = "<unknown creator>";
const char *RightAuthenticationLogger::authenticatorStr = "known UID ";
const char *RightAuthenticationLogger::clientStr = "client ";
const char *RightAuthenticationLogger::authCreatorStr = "creator ";
const char *RightAuthenticationLogger::authenticatedAsStr = "authenticated as ";
const char *RightAuthenticationLogger::leastPrivStr = "least-privilege";
RightAuthenticationLogger::RightAuthenticationLogger(const AuditToken &srcToken, short auEvent)
: AuditLogger(srcToken, auEvent), RightLogger()
{
}
RightAuthenticationLogger::RightAuthenticationLogger(const audit_token_t *srcToken, short auEvent)
: AuditLogger(srcToken, auEvent), RightLogger()
{
}
void
RightAuthenticationLogger::writeCommon()
{
writeSubject();
writeToken(au_to_text(mRight.c_str()), "right");
}
void
RightAuthenticationLogger::logSuccess(uid_t authenticator, uid_t target, const char *targetName)
{
if (false == open())
return;
writeCommon();
writeToken(au_to_arg32(1, authenticatorStr, authenticator), "authenticator");
string tmpStr(authenticatedAsStr);
tmpStr += targetName ? targetName : unknownUserStr;
writeToken(au_to_arg32(2, tmpStr.c_str(), target), "target");
writeReturn(0, 0);
close();
}
void
RightAuthenticationLogger::logAuthorizationResult(const char *client, const char *authCreator, int errcode)
{
if (false == open())
return;
writeCommon();
string tmpStr(clientStr);
tmpStr += client ? client : unknownClientStr;
writeToken(au_to_text(tmpStr.c_str()), "Authorization client");
tmpStr.clear();
tmpStr = authCreatorStr;
tmpStr += authCreator ? authCreator : unknownAuthCreatorStr;
writeToken(au_to_text(tmpStr.c_str()), "Authorization creator");
if (errAuthorizationSuccess == errcode)
writeReturn(0, 0);
else
writeReturn(EPERM, errcode);
close();
}
void
RightAuthenticationLogger::logLeastPrivilege(uid_t userId, bool isAuthorizingUser)
{
if (false == open())
return;
writeCommon();
writeToken(au_to_text(leastPrivStr), leastPrivStr);
writeReturn(0, 0);
close();
}
void
RightAuthenticationLogger::logFailure(uid_t authenticator, const char *targetName)
{
if (false == open())
return;
writeCommon();
writeToken(au_to_arg32(1, authenticatorStr, authenticator), "authenticator");
if (NULL == targetName)
writeToken(au_to_text(unknownUserStr), "target username");
else
writeToken(au_to_text(targetName), "target username");
writeReturn(EPERM, errAuthorizationDenied);
close();
}
}
}
}