#include "agentquery.h"
#include "authority.h"
#include "server.h"
#include "session.h"
using namespace SecurityAgent;
SecurityAgentQuery::SecurityAgentQuery(uid_t clientUID,
Session &clientSession) :
SecurityAgent::Client(clientUID, clientSession.bootstrapPort()),
mClientSession(clientSession)
{
}
SecurityAgentQuery::~SecurityAgentQuery()
{
}
void
SecurityAgentQuery::activate(const char *bootstrapName = NULL)
{
if (isActive())
return;
if (!(mClientSession.attributes() & sessionHasGraphicAccess))
CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION);
Server::active().longTermActivity();
Server::connection().useAgent(this);
SecurityAgent::Client::activate(bootstrapName);
}
void
SecurityAgentQuery::terminate()
{
if (!isActive())
return;
Server::connection(true).useAgent(NULL);
SecurityAgent::Client::terminate();
}
void QueryKeychainUse::operator () (const char *database, const char *description,
AclAuthorization action)
{
queryKeychainAccess(Server::connection().process.clientCode(),
Server::connection().process.pid(),
database, description, action, needPassphrase, *this);
}
void QueryPassphrase::query(const AccessCredentials *cred, CSSM_SAMPLE_TYPE sampleType)
{
CssmAutoData passphrase(CssmAllocator::standard(CssmAllocator::sensitive));
if (SecurityServerAcl::getBatchPassphrase(cred, sampleType, passphrase)) {
if (accept(passphrase, false) == noReason)
return;
else
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PASSPHRASE); } else {
unsigned int retryCount = 0;
queryInteractive(passphrase);
while (Reason reason = accept(passphrase, true)) {
if (++retryCount > maxRetries) {
cancelStagedQuery(tooManyTries);
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PASSPHRASE); } else {
retryInteractive(passphrase, reason);
}
}
finishStagedQuery();
}
}
void QueryUnlock::operator () (const AccessCredentials *cred)
{
query(cred, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK);
}
Reason QueryUnlock::accept(CssmManagedData &passphrase, bool)
{
return database.decode(passphrase) ? noReason : invalidPassphrase;
}
void QueryUnlock::queryInteractive(CssmOwnedData &passphrase)
{
char passString[maxPassphraseLength];
queryUnlockDatabase(Server::connection().process.clientCode(),
Server::connection().process.pid(),
database.dbName(), passString);
passphrase.copy(passString, strlen(passString));
}
void QueryUnlock::retryInteractive(CssmOwnedData &passphrase, Reason reason)
{
char passString[maxPassphraseLength];
retryUnlockDatabase(reason, passString);
passphrase.copy(passString, strlen(passString));
}
void QueryNewPassphrase::operator () (const AccessCredentials *cred, CssmOwnedData &passphrase)
{
query(cred, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK);
passphrase = mPassphrase;
}
Reason QueryNewPassphrase::accept(CssmManagedData &passphrase, bool canRetry)
{
if (!canRetry) {
mPassphrase = passphrase;
return noReason;
}
if (mPassphraseValid && passphrase.get() == mPassphrase)
return noReason;
mPassphrase = passphrase;
mPassphraseValid = true;
if (mPassphrase.length() == 0)
return passphraseIsNull;
const char *passString = mPassphrase;
if (strlen(passString) < 6)
return passphraseTooSimple;
return noReason;
}
void QueryNewPassphrase::queryInteractive(CssmOwnedData &passphrase)
{
char passString[maxPassphraseLength];
queryNewPassphrase(Server::connection().process.clientCode(),
Server::connection().process.pid(),
dbCommon.dbName(), initialReason, passString);
passphrase.copy(passString, strlen(passString));
}
void QueryNewPassphrase::retryInteractive(CssmOwnedData &passphrase, Reason reason)
{
char passString[maxPassphraseLength];
retryNewPassphrase(reason, passString);
passphrase.copy(passString, strlen(passString));
}
QueryAuthorizeByGroup::QueryAuthorizeByGroup(uid_t clientUID, const AuthorizationToken &auth) :
SecurityAgentQuery(clientUID, auth.session),
authorization(auth), mActive(false) { }
void QueryAuthorizeByGroup::cancel(Reason reason)
{
if (mActive) {
cancelStagedQuery(reason);
mActive = false;
}
}
void QueryAuthorizeByGroup::done()
{
if (mActive) {
finishStagedQuery();
mActive = false;
}
}
uid_t QueryAuthorizeByGroup::uid()
{
return Server::connection().process.uid();
}
bool QueryAuthorizeByGroup::operator () (const char *group, const char *candidateUser,
char username[maxUsernameLength], char passphrase[maxPassphraseLength], Reason reason)
{
if (mActive) {
return retryAuthorizationAuthenticate(reason, username, passphrase);
} else {
bool result = authorizationAuthenticate(authorization.creatorCode(),
Server::connection().process.pid(), group, candidateUser, username, passphrase);
mActive = true;
return result;
}
}
QueryInvokeMechanism::QueryInvokeMechanism(uid_t clientUID, const AuthorizationToken &auth) :
SecurityAgentQuery(clientUID, auth.session) {}
bool QueryInvokeMechanism::operator () (const string &inPluginId, const string &inMechanismId, const AuthorizationValueVector *inArguments, const AuthItemSet &inHints, const AuthItemSet &inContext, AuthorizationResult *outResult, AuthorizationItemSet *&outHintsPtr, AuthorizationItemSet *&outContextPtr)
{
bool result = invokeMechanism(inPluginId, inMechanismId, inArguments, inHints, inContext, outResult, outHintsPtr, outContextPtr);
return result;
}
QueryTerminateAgent::QueryTerminateAgent(uid_t clientUID, const AuthorizationToken &auth) :
SecurityAgentQuery(clientUID, auth.session) {}
void QueryTerminateAgent::operator () ()
{
terminateAgent();
}