#include "authority.h"
#include "server.h"
#include "connection.h"
#include "session.h"
#include "process.h"
#include "AuthorizationWalkers.h"
using Authorization::Right;
AuthorizationToken::AuthMap AuthorizationToken::authMap; Mutex AuthorizationToken::authMapLock;
Authority::Authority(const char *configFile)
: Authorization::Engine(configFile)
{
}
Authority::~Authority()
{
}
AuthorizationToken::AuthorizationToken(Session &ssn, const CredentialSet &base)
: session(ssn), mBaseCreds(base), mTransferCount(INT_MAX),
mCreatorUid(Server::connection().process.uid()),
mCreatorCode(Server::connection().process.clientCode()), mInfoSet(NULL)
{
Server::active().random(mHandle);
StLock<Mutex> _(authMapLock);
authMap[mHandle] = this;
session.addAuthorization(this);
IFDEBUG(debug("SSauth", "Authorization %p created using %d credentials; owner=%s",
this, int(mBaseCreds.size()),
mCreatorCode ? mCreatorCode->encode().c_str() : "unknown"));
}
AuthorizationToken::~AuthorizationToken()
{
assert(mUsingProcesses.empty());
if (session.removeAuthorization(this))
delete &session;
if (mInfoSet)
{
debug("SSauth", "Authorization %p destroying context @%p", this, mInfoSet);
CssmAllocator::standard().free(mInfoSet); }
debug("SSauth", "Authorization %p destroyed", this);
}
AuthorizationToken &AuthorizationToken::find(const AuthorizationBlob &blob)
{
StLock<Mutex> _(authMapLock);
AuthMap::iterator it = authMap.find(blob);
if (it == authMap.end())
Authorization::Error::throwMe(errAuthorizationInvalidRef);
return *it->second;
}
AuthorizationToken::Deleter::Deleter(const AuthorizationBlob &blob)
: lock(authMapLock)
{
AuthMap::iterator it = authMap.find(blob);
if (it == authMap.end())
Authorization::Error::throwMe(errAuthorizationInvalidRef);
mAuth = it->second;
}
void AuthorizationToken::Deleter::remove()
{
if (mAuth) {
authMap.erase(mAuth->handle());
delete mAuth;
mAuth = NULL;
}
}
CredentialSet AuthorizationToken::effectiveCreds() const
{
IFDEBUG(debug("SSauth", "Authorization %p grabbing session %p creds %p", this, &session, &session.authCredentials()));
CredentialSet result = session.authCredentials();
for (CredentialSet::const_iterator it = mBaseCreds.begin(); it != mBaseCreds.end(); it++)
if (!(*it)->isShared())
result.insert(*it);
return result;
}
void AuthorizationToken::mergeCredentials(const CredentialSet &add)
{
debug("SSauth", "Authorization %p merge creds %p", this, &add);
for (CredentialSet::const_iterator it = add.begin(); it != add.end(); it++) {
mBaseCreds.erase(*it);
mBaseCreds.insert(*it);
}
debug("SSauth", "Authorization %p merged %d new credentials for %d total",
this, int(add.size()), int(mBaseCreds.size()));
}
void AuthorizationToken::addProcess(Process &proc)
{
StLock<Mutex> _(mLock);
mUsingProcesses.insert(&proc);
debug("SSauth", "Authorization %p added process %p(%d)", this, &proc, proc.pid());
}
bool AuthorizationToken::endProcess(Process &proc)
{
StLock<Mutex> _(mLock);
assert(mUsingProcesses.find(&proc) != mUsingProcesses.end());
mUsingProcesses.erase(&proc);
IFDEBUG(debug("SSauth", "Authorization %p removed process %p(%d)%s",
this, &proc, proc.pid(), mUsingProcesses.empty() ? " FINAL" : ""));
return mUsingProcesses.empty();
}
bool AuthorizationToken::mayExternalize(Process &) const
{
return mTransferCount > 0;
}
bool AuthorizationToken::mayInternalize(Process &, bool countIt)
{
StLock<Mutex> _(mLock);
if (mTransferCount > 0) {
if (countIt) {
mTransferCount--;
debug("SSauth", "Authorization %p decrement intcount to %d", this, mTransferCount);
}
return true;
}
return false;
}
AuthorizationItemSet &
AuthorizationToken::infoSet()
{
StLock<Mutex> _(mLock); MutableRightSet tempInfoSet(mInfoSet);
AuthorizationItemSet *returnSet = Copier<AuthorizationItemSet>(tempInfoSet, CssmAllocator::standard()).keep();
debug("SSauth", "Authorization %p returning context %p", this, returnSet);
return *returnSet;
}
void
AuthorizationToken::setInfoSet(AuthorizationItemSet &newInfoSet)
{
StLock<Mutex> _(mLock); if (mInfoSet)
CssmAllocator::standard().free(mInfoSet); debug("SSauth", "Authorization %p context %p -> %p", this, mInfoSet, &newInfoSet);
mInfoSet = &newInfoSet;
}
void
AuthorizationToken::setCredentialInfo(const Credential &inCred)
{
StLock<Mutex> _(mLock);
MutableRightSet dstInfoSet;
char uid_string[16];
if (snprintf(uid_string, sizeof(uid_string), "%u", inCred->uid()) >=
sizeof(uid_string))
uid_string[0] = '\0';
Right uidHint("uid", uid_string ? strlen(uid_string) + 1 : 0, uid_string );
dstInfoSet.push_back(uidHint);
const char *user = inCred->username().c_str();
Right userHint("username", user ? strlen(user) + 1 : 0, user );
dstInfoSet.push_back(userHint);
AuthorizationItemSet *newInfoSet = Copier<AuthorizationItemSet>(dstInfoSet, CssmAllocator::standard()).keep();
CssmAllocator::standard().free(mInfoSet); mInfoSet = newInfoSet;
}