#include "process.h"
#include "server.h"
#include "session.h"
#include "tempdatabase.h"
#include "child.h" // ServerChild (really UnixPlusPlus::Child)::find()
#include <security_utilities/ccaudit.h>
#include <security_utilities/logging.h> //@@@ debug only
#include "agentquery.h"
Process::Process(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit)
: mTaskPort(taskPort), mByteFlipped(false), mPid(audit.pid()), mUid(audit.euid()), mGid(audit.egid()), mAudit(audit)
{
StLock<Mutex> _(*this);
xpc_transaction_begin();
parent(Session::find(audit.sessionId(), true));
if (mTaskPort.pid() != mPid) {
secnotice("SecServer", "Task/pid setup mismatch pid=%d task=%d(%d)",
mPid, mTaskPort.port(), mTaskPort.pid());
CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); }
setup(info);
ClientIdentification::setup(this->audit_token());
if(!processCode()) {
secnotice("SecServer", "no process created in setup, old pid=%d old task=%d(%d)",
mPid, mTaskPort.port(), mTaskPort.pid());
CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED);
}
mTaskPort.modRefs(MACH_PORT_RIGHT_SEND, 1);
if (this->pid() == getpid() || ServerChild::find<ServerChild>(this->pid())) xpc_transaction_end();
secinfo("SecServer", "%p client new: pid:%d session:%d %s taskPort:%d uid:%d gid:%d", this, this->pid(), this->session().sessionId(),
(char *)codePath(this->processCode()).c_str(), taskPort.port(), mUid, mGid);
}
void Process::reset(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit)
{
StLock<Mutex> _(*this);
if (taskPort != mTaskPort) {
secnotice("SecServer", "Process %p(%d) reset mismatch (tp %d-%d)",
this, pid(), taskPort.port(), mTaskPort.port());
}
setup(info);
CFCopyRef<SecCodeRef> oldCode = processCode();
ClientIdentification::setup(this->audit_token()); if (CFEqual(oldCode, processCode())) {
secnotice("SecServer", "%p Client reset amnesia", this);
} else {
secnotice("SecServer", "%p Client reset full", this);
}
}
void Process::setup(const ClientSetupInfo *info)
{
assert(info);
uint32 pversion;
if (info->order == 0x1234) { pversion = info->version;
mByteFlipped = false;
} else if (info->order == 0x34120000) { pversion = flip(info->version);
mByteFlipped = true;
} else CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION);
if (pversion != SSPROTOVERSION)
CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION);
}
Process::~Process()
{
secinfo("SecServer", "%p client release: %d", this, this->pid());
if (mTaskPort) {
mTaskPort.deallocate();
}
xpc_transaction_end();
}
void Process::kill()
{
StLock<Mutex> _(*this);
mLocalStore = NULL;
PerProcess::kill();
}
Session& Process::session() const
{
return parent<Session>();
}
void Process::checkSession(const audit_token_t &auditToken)
{
Security::CommonCriteria::AuditToken audit(auditToken);
if (audit.sessionId() != this->session().sessionId())
this->changeSession(audit.sessionId());
}
LocalDatabase &Process::localStore()
{
StLock<Mutex> _(*this);
if (!mLocalStore)
mLocalStore = new TempDatabase(*this);
return *mLocalStore;
}
Key *Process::makeTemporaryKey(const CssmKey &key, CSSM_KEYATTR_FLAGS moreAttributes,
const AclEntryPrototype *owner)
{
return safer_cast<TempDatabase&>(localStore()).makeKey(key, moreAttributes, owner);
}
void Process::changeSession(Session::SessionId sessionId)
{
parent(Session::find(sessionId, true));
secnotice("SecServer", "%p client change session to %d", this, this->session().sessionId());
}
#if defined(DEBUGDUMP)
void Process::dumpNode()
{
PerProcess::dumpNode();
if (mByteFlipped)
Debug::dump(" FLIPPED");
Debug::dump(" task=%d pid=%d uid/gid=%d/%d",
mTaskPort.port(), mPid, mUid, mGid);
ClientIdentification::dump();
}
#endif //DEBUGDUMP