#include "agentquery.h"
#include "server.h"
using namespace SecurityAgent;
SecurityAgentQuery::SecurityAgentQuery()
{
Server::active().longTermActivity();
Server::connection().useAgent(this);
}
SecurityAgentQuery::~SecurityAgentQuery()
{
Server::connection(true).useAgent(NULL);
}
void QueryKeychainUse::operator () (const char *database, const char *description,
AclAuthorization action)
{
queryKeychainAccess(Server::connection().process.clientCode(),
Server::connection().process.pid(),
database, description, action, *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));
}
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(Server::connection().process.clientCode(),
Server::connection().process.pid(), group, candidateUser, username, passphrase);
mActive = true;
return result;
}
}