*
* @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
#include "session.h"
#include "tempdatabase.h"
#include "authority.h"
-#include "flippers.h"
+#include "child.h" // ServerChild (really UnixPlusPlus::Child)::find()
+
+#include <security_utilities/logging.h> //@@@ 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<Mutex> _(*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<ServerChild>(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<Mutex> _(*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<SecCodeRef> 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",
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)
}
-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<Mutex> _(*this);
if (!mLocalStore)
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<TempDatabase&>(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());
}
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
}
-//
-// 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
//
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