X-Git-Url: https://git.saurik.com/apple/securityd.git/blobdiff_plain/ee396ef47db58c01c7ceaecfec60781c95ffeea1..4cd1cad0dea00daa03e1b54fdf2797a02373ad5b:/src/process.cpp?ds=inline diff --git a/src/process.cpp b/src/process.cpp index 87caf65..606e949 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -30,72 +30,86 @@ #include "session.h" #include "tempdatabase.h" #include "authority.h" -#include "flippers.h" +#include "child.h" // ServerChild (really UnixPlusPlus::Child)::find() + +#include //@@@ debug only +#include "agentquery.h" // // Construct a Process object. // -Process::Process(Port servicePort, TaskPort taskPort, - const ClientSetupInfo *info, const char *identity, const CommonCriteria::AuditToken &audit) +Process::Process(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit) : mTaskPort(taskPort), mByteFlipped(false), mPid(audit.pid()), mUid(audit.euid()), mGid(audit.egid()) { + StLock _(*this); + // set parent session - parent(Session::find(servicePort)); + parent(Session::find(audit.sessionId(), true)); // let's take a look at our wannabe client... if (mTaskPort.pid() != mPid) { - secdebug("SS", "Task/pid setup mismatch pid=%d task=%d(%d) for %s", - mPid, mTaskPort.port(), mTaskPort.pid(), - (identity && identity[0]) ? identity : "(unknown)"); + secdebug("SS", "Task/pid setup mismatch pid=%d task=%d(%d)", + mPid, mTaskPort.port(), mTaskPort.pid()); CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); // you lied! } - setup(info, identity); - - secdebug("SS", "New process %p(%d) uid=%d gid=%d session=%p TP=%d %sfor %s", - this, mPid, mUid, mGid, &session(), - mTaskPort.port(), - mByteFlipped ? "FLIP " : "", - (identity && identity[0]) ? identity : "(unknown)"); + setup(info); + ClientIdentification::setup(this->pid()); + + // NB: ServerChild::find() should only be used to determine + // *existence*. Don't use the returned Child object for anything else, + // as it is not protected against its underlying process's destruction. + if (this->pid() == getpid() // called ourselves (through some API). Do NOT record this as a "dirty" transaction + || ServerChild::find(this->pid())) // securityd's child; do not mark this txn dirty + VProc::Transaction::deactivate(); + + if (SECURITYD_CLIENT_NEW_ENABLED()) + SECURITYD_CLIENT_NEW(this, this->pid(), &this->session(), + (char *)codePath(this->processCode()).c_str(), taskPort, mUid, mGid, mByteFlipped); } // // Screen a process setup request for an existing process. -// This usually means the client has called exec(2) and forgotten all about itself. -// Though it could be a nefarious attempt to fool us... +// This means the client has requested intialization even though we remember having +// talked to it in the past. This could either be an exec(2), or the client could just +// have forgotten all about its securityd client state. Or it could be an attack... // -void Process::reset(Port servicePort, TaskPort taskPort, - const ClientSetupInfo *info, const char *identity, const CommonCriteria::AuditToken &audit) +void Process::reset(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit) { - if (servicePort != session().servicePort() || taskPort != mTaskPort) { - secdebug("SS", "Process %p(%d) reset mismatch (sp %d-%d, tp %d-%d) for %s", - this, pid(), servicePort.port(), session().servicePort().port(), taskPort.port(), mTaskPort.port(), - (identity && identity[0]) ? identity : "(unknown)"); - CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); // liar + StLock _(*this); + if (taskPort != mTaskPort) { + secdebug("SS", "Process %p(%d) reset mismatch (tp %d-%d)", + this, pid(), taskPort.port(), mTaskPort.port()); + //@@@ CssmError::throwMe(CSSM_ERRCODE_VERIFICATION_FAILURE); // liar } + setup(info); + CFCopyRef oldCode = processCode(); - setup(info, identity); - - secdebug("SS", "process %p(%d) has reset; now %sfor %s", - this, mPid, mByteFlipped ? "FLIP " : "", - (identity && identity[0]) ? identity : "(unknown)"); + ClientIdentification::setup(this->pid()); // re-constructs processCode() + if (CFEqual(oldCode, processCode())) { + SECURITYD_CLIENT_RESET_AMNESIA(this); + } else { + SECURITYD_CLIENT_RESET_FULL(this); + CodeSigningHost::reset(); + } } // // Common set processing // -void Process::setup(const ClientSetupInfo *info, const char *identity) +void Process::setup(const ClientSetupInfo *info) { // process setup info assert(info); uint32 pversion; if (info->order == 0x1234) { // right side up pversion = info->version; + mByteFlipped = false; } else if (info->order == 0x34120000) { // flip side up - pversion = ntohl(info->version); + pversion = flip(info->version); mByteFlipped = true; } else // non comprende CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); @@ -103,17 +117,6 @@ void Process::setup(const ClientSetupInfo *info, const char *identity) // check wire protocol version if (pversion != SSPROTOVERSION) CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); - - // process identity (if given) - try { - mClientCode = OSXCode::decode(identity); - mClientIdent = deferred; // will calculate code identity when needed - } catch (...) { - secdebug("SS", "process %p(%d) identity decode threw exception", this, pid()); - mClientCode = NULL; - mClientIdent = unknown; // no chance to squeeze a code identity from this - secdebug("SS", "process %p(%d) no clientCode - marked anonymous", this, pid()); - } } @@ -122,6 +125,8 @@ void Process::setup(const ClientSetupInfo *info, const char *identity) // Process::~Process() { + SECURITYD_CLIENT_RELEASE(this, this->pid()); + // tell all our authorizations that we're gone IFDEBUG(if (!mAuthorizations.empty()) secdebug("SS", "Process %p(%d) clearing %d authorizations", @@ -133,9 +138,6 @@ Process::~Process() if (auth->endProcess(*this)) delete auth; } - - // no need to lock here; the client process has no more active threads - secdebug("SS", "Process %p(%d) has died", this, mPid); // release our name for the process's task port if (mTaskPort) @@ -160,6 +162,14 @@ Session& Process::session() const } +void Process::checkSession(const audit_token_t &auditToken) +{ + AuditToken audit(auditToken); + if (audit.sessionId() != this->session().sessionId()) + this->changeSession(audit.sessionId()); +} + + LocalDatabase &Process::localStore() { StLock _(*this); @@ -179,49 +189,11 @@ Key *Process::makeTemporaryKey(const CssmKey &key, CSSM_KEYATTR_FLAGS moreAttrib // Change the session of a process. // This is the result of SessionCreate from a known process client. // -void Process::changeSession(Port servicePort) +void Process::changeSession(Session::SessionId sessionId) { // re-parent - parent(Session::find(servicePort)); - - secdebug("SS", "process %p(%d) changed session to %p", this, pid(), &session()); -} - - -// -// CodeSignatures implementation of Identity. -// The caller must make sure we have a valid (not necessarily hash-able) clientCode(). -// -string Process::getPath() const -{ - assert(mClientCode); - return mClientCode->canonicalPath(); -} - -const CssmData Process::getHash(CodeSigning::OSXSigner &signer) const -{ - switch (mClientIdent) { - case deferred: - try { - // try to calculate our signature hash (first time use) - mCachedSignature.reset(mClientCode->sign(signer)); - assert(mCachedSignature.get()); - mClientIdent = known; - secdebug("SS", "process %p(%d) code signature computed", this, pid()); - break; - } catch (...) { - // couldn't get client signature (unreadable, gone, hack attack, ...) - mClientIdent = unknown; - secdebug("SS", "process %p(%d) no code signature - anonymous", this, pid()); - CssmError::throwMe(CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION); - } - case known: - assert(mCachedSignature.get()); - break; - case unknown: - CssmError::throwMe(CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION); - } - return CssmData(*mCachedSignature); + parent(Session::find(sessionId, true)); + SECURITYD_CLIENT_CHANGE_SESSION(this, &this->session()); } @@ -267,21 +239,6 @@ bool Process::removeAuthorization(AuthorizationToken *auth) } -// -// Notification client maintainance -// -void Process::requestNotifications(Port port, SecurityServer::NotificationDomain domain, SecurityServer::NotificationMask events) -{ - new ProcessListener(*this, port, domain, events); -} - -void Process::stopNotifications(Port port) -{ - if (!Listener::remove(port)) - CssmError::throwMe(CSSMERR_CSSM_INVALID_HANDLE_USAGE); //@@@ bad name (should be "no such callback") -} - - // // Debug dump support // @@ -294,21 +251,8 @@ void Process::dumpNode() Debug::dump(" FLIPPED"); Debug::dump(" task=%d pid=%d uid/gid=%d/%d", mTaskPort.port(), mPid, mUid, mGid); - if (mClientCode) { - Debug::dump(" client=%s", mClientCode->canonicalPath().c_str()); - switch (mClientIdent) { - case deferred: - break; - case known: - Debug::dump("[OK]"); - break; - case unknown: - Debug::dump("[UNKNOWN]"); - break; - } - } else { - Debug::dump(" NO CLIENT ID"); - } + CodeSigningHost::dump(); + ClientIdentification::dump(); } #endif //DEBUGDUMP