X-Git-Url: https://git.saurik.com/apple/securityd.git/blobdiff_plain/eeadf2e6470f45ea0275a6019635573f2a7b5a2c..4cd1cad0dea00daa03e1b54fdf2797a02373ad5b:/src/process.cpp diff --git a/src/process.cpp b/src/process.cpp index 7dce80d..606e949 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -3,8 +3,6 @@ * * @APPLE_LICENSE_HEADER_START@ * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. - * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -32,59 +30,103 @@ #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, uid_t uid, gid_t gid) - : mTaskPort(taskPort), mByteFlipped(false), mUid(uid), mGid(gid), - mClientIdent(deferred) +Process::Process(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit) + : mTaskPort(taskPort), mByteFlipped(false), mPid(audit.pid()), mUid(audit.euid()), mGid(audit.egid()) { - // examine info passed - assert(info); - uint32 pversion = info->version; - if (pversion == SSPROTOVERSION) { - // correct protocol, same byte order, cool - } else { - Flippers::flip(pversion); - if (pversion == SSPROTOVERSION) { - // correct protocol, reversed byte order - mByteFlipped = true; - } else { - // unsupported protocol version - CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); - } - } + StLock _(*this); // set parent session - parent(Session::find(servicePort)); + parent(Session::find(audit.sessionId(), true)); // let's take a look at our wannabe client... - mPid = mTaskPort.pid(); - - 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)"); - - try { - mClientCode = CodeSigning::OSXCode::decode(identity); - } catch (...) { - secdebug("SS", "process %p(%d) identity decode threw exception", this, pid()); + if (mTaskPort.pid() != mPid) { + 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! } - if (!mClientCode) { - mClientIdent = unknown; // no chance to squeeze a code identity from this - secdebug("SS", "process %p(%d) no clientCode - marked anonymous", this, pid()); + + 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 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(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit) +{ + 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(); + + 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) +{ + // 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 = flip(info->version); + mByteFlipped = true; + } else // non comprende + CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); + + // check wire protocol version + if (pversion != SSPROTOVERSION) + CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); +} + + +// +// Clean up a Process object +// 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", @@ -96,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) @@ -123,7 +162,15 @@ Session& Process::session() const } -Database &Process::localStore() +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); if (!mLocalStore) @@ -131,54 +178,22 @@ Database &Process::localStore() return *mLocalStore; } - -// -// Change the session of a process. -// This is the result of SessionCreate from a known process client. -// -void Process::changeSession(Port servicePort) +Key *Process::makeTemporaryKey(const CssmKey &key, CSSM_KEYATTR_FLAGS moreAttributes, + const AclEntryPrototype *owner) { - // re-parent - parent(Session::find(servicePort)); - - secdebug("SS", "process %p(%d) changed session to %p", this, pid(), &session()); + return safer_cast(localStore()).makeKey(key, moreAttributes, owner); } // -// CodeSignatures implementation of Identity. -// The caller must make sure we have a valid (not necessarily hash-able) clientCode(). +// Change the session of a process. +// This is the result of SessionCreate from a known process client. // -string Process::getPath() const -{ - assert(mClientCode); - return mClientCode->canonicalPath(); -} - -const CssmData Process::getHash(CodeSigning::OSXSigner &signer) const +void Process::changeSession(Session::SessionId sessionId) { - 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); + // re-parent + parent(Session::find(sessionId, true)); + SECURITYD_CLIENT_CHANGE_SESSION(this, &this->session()); } @@ -210,7 +225,6 @@ bool Process::removeAuthorization(AuthorizationToken *auth) Iter it = mAuthorizations.lower_bound(auth); bool isLast; if (it == mAuthorizations.end() || auth != *it) { - Syslog::error("process is missing authorization to remove"); // temp. diagnostic isLast = true; } else { Iter next = it; ++next; // following element @@ -225,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 // @@ -252,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