AuthorizationMechEval.cpp [plain text]
#include "AuthorizationMechEval.h"
#include <security_utilities/logging.h>
#include <bsm/audit_uevents.h>
#include "ccaudit_extensions.h"
namespace Authorization {
using namespace CommonCriteria::Securityd;
AgentMechanismRef::AgentMechanismRef(const AuthHostType type, Session &session) :
RefPointer<QueryInvokeMechanism>(new QueryInvokeMechanism(type, session)) {}
AgentMechanismEvaluator::AgentMechanismEvaluator(uid_t uid, Session& session, const vector<string>& inMechanisms) :
mMechanisms(inMechanisms), mClientUid(uid), mSession(session)
{
}
OSStatus
AgentMechanismEvaluator::run(const AuthValueVector &inArguments, const AuthItemSet &inHints, const AuthorizationToken &auth)
{
AuthMechLogger logger(auth.creatorAuditToken(), AUE_ssauthmech);
string rightName = "<unknown right>";
try
{
AuthorizationValue val = inArguments.at(0)->value();
string tmpstr(static_cast<const char *>(val.data), val.length);
logger.setRight(tmpstr);
rightName.clear();
rightName = tmpstr;
}
catch (...) { }
const AuthItemSet &inContext = const_cast<AuthorizationToken &>(auth).infoSet();
vector<std::string>::const_iterator currentMechanism = mMechanisms.begin();
AuthorizationResult result = kAuthorizationResultAllow;
AuthItemSet hints = inHints;
AuthItemSet context = inContext;
context.insert(mStickyContext.begin(), mStickyContext.end());
while ( (result == kAuthorizationResultAllow) &&
(currentMechanism != mMechanisms.end()) ) {
SECURITYD_AUTH_MECH(&auth, (char *)(*currentMechanism).c_str());
logger.setCurrentMechanism(*currentMechanism);
ClientMap::iterator iter = mClients.find(*currentMechanism);
if (iter == mClients.end())
{
string::size_type extPlugin = currentMechanism->find(':');
if (extPlugin != string::npos)
{
string pluginIn(currentMechanism->substr(0, extPlugin));
string mechanismIn, authhostIn;
string::size_type extMechanism = currentMechanism->rfind(',');
AuthHostType hostType = securityAgent;
if (extMechanism != string::npos)
{
if (extMechanism < extPlugin)
{
string auditMsg = "badly formed mechanism name; ending rule evaluation";
Syslog::alert("Right '%s', mech '%s': %s", rightName.c_str(), (*currentMechanism).c_str(), auditMsg.c_str());
logger.logFailure(auditMsg);
return errAuthorizationInternal;
}
mechanismIn = currentMechanism->substr(extPlugin + 1, extMechanism - extPlugin - 1);
authhostIn = currentMechanism->substr(extMechanism + 1);
if (authhostIn == "privileged")
hostType = privilegedAuthHost;
}
else
mechanismIn = currentMechanism->substr(extPlugin + 1);
secdebug("AuthEvalMech", "external mechanism %s:%s", pluginIn.c_str(), mechanismIn.c_str());
AgentMechanismRef client(hostType, mSession);
client->initialize(pluginIn, mechanismIn, inArguments);
mClients.insert(ClientMap::value_type(*currentMechanism, client));
}
else if (*currentMechanism == "authinternal")
{
secdebug("AuthEvalMech", "performing authentication");
result = authinternal(context);
if (kAuthorizationResultAllow == result)
{
logger.logSuccess();
}
else {
logger.logFailure();
}
}
else if (*currentMechanism == "push_hints_to_context")
{
secdebug("AuthEvalMech", "evaluate push_hints_to_context");
logger.logSuccess();
result = kAuthorizationResultAllow;
context = hints;
}
else
{
string auditMsg = "unknown mechanism; ending rule evaluation";
Syslog::alert("Right '%s', mech '%s': %s", rightName.c_str(), (*currentMechanism).c_str(), auditMsg.c_str());
logger.logFailure(auditMsg);
return errAuthorizationInternal;
}
}
iter = mClients.find(*currentMechanism);
if (iter != mClients.end())
{
try
{
AgentMechanismRef &client = iter->second;
client->run(inArguments, hints, context, &result);
bool interrupted = false;
while (client->state() == client->current)
{
vector<std::string>::const_iterator checkMechanism = mMechanisms.begin();
while (*checkMechanism != *currentMechanism) {
ClientMap::iterator iter2 = mClients.find(*checkMechanism);
if (iter2->second->state() == iter2->second->interrupting)
{
client->deactivate();
while (client->state() == client->deactivating)
client->receive();
string auditMsg = "evaluation interrupted by ";
auditMsg += (iter2->first).c_str();
auditMsg += "; restarting evaluation there";
secdebug("AuthEvalMech", "%s", auditMsg.c_str());
logger.logInterrupt(auditMsg);
interrupted = true;
hints = iter2->second->inHints();
context = iter2->second->inContext();
currentMechanism = checkMechanism;
break;
}
else
checkMechanism++;
}
if (client->state() == client->current)
client->receive();
}
if (interrupted)
{
uint32_t reason = SecurityAgent::worldChanged;
AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason));
hints.erase(retryHint); hints.insert(retryHint);
result = kAuthorizationResultAllow;
continue;
}
else
secdebug("AuthEvalMech", "evaluate(%s) with result: %u.", (iter->first).c_str(), (uint32_t)result);
}
catch (...) {
string auditMsg = "exception during evaluation of ";
auditMsg += (iter->first).c_str();
secdebug("AuthEvalMech", "%s", auditMsg.c_str());
logger.logFailure(auditMsg);
result = kAuthorizationResultUndefined;
}
}
if (result == kAuthorizationResultAllow)
{
logger.logSuccess();
currentMechanism++;
}
}
if ((result == kAuthorizationResultUserCanceled) ||
(result == kAuthorizationResultAllow))
{
mHints = hints;
mContext.clear();
AuthItemSet::const_iterator end = context.end();
for (AuthItemSet::const_iterator it = context.begin(); it != end; ++it) {
const AuthItemRef &item = *it;
if (item->flags() != kAuthorizationContextFlagSticky)
mContext.insert(item);
}
if (result == kAuthorizationResultUserCanceled)
logger.logFailure(NULL, errAuthorizationCanceled);
}
else if (result == kAuthorizationResultDeny)
{
mStickyContext.clear();
AuthItemSet::const_iterator end = context.end();
for (AuthItemSet::const_iterator it = context.begin(); it != end; ++it) {
const AuthItemRef &item = *it;
if (item->flags() == kAuthorizationContextFlagSticky)
mStickyContext.insert(item);
}
logger.logFailure();
}
switch(result)
{
case kAuthorizationResultDeny:
return errAuthorizationDenied;
case kAuthorizationResultUserCanceled:
return errAuthorizationCanceled;
case kAuthorizationResultAllow:
return errAuthorizationSuccess;
case kAuthorizationResultUndefined:
return errAuthorizationInternal;
default:
{
Syslog::alert("Right '%s': unexpected error result (%u)", rightName.c_str(), result);
logger.logFailure("unexpected error result", result);
return errAuthorizationInternal;
}
}
}
AuthorizationResult AgentMechanismEvaluator::authinternal(AuthItemSet &context)
{
secdebug("AuthEvalMech", "evaluate authinternal");
do {
AuthItemSet::iterator found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentUsername) );
if (found == context.end())
break;
string username(static_cast<const char *>((*found)->value().data), (*found)->value().length);
secdebug("AuthEvalMech", "found username");
found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentPassword) );
if (found == context.end())
break;
string password(static_cast<const char *>((*found)->value().data), (*found)->value().length);
secdebug("AuthEvalMech", "found password");
Credential newCredential(username, password, true); if (newCredential->isValid())
return kAuthorizationResultAllow;
} while (0);
return kAuthorizationResultDeny;
}
}