]> git.saurik.com Git - apple/securityd.git/blobdiff - src/process.cpp
securityd-55199.3.tar.gz
[apple/securityd.git] / src / process.cpp
index 7dce80dfe205d8c6abd28648928da38925117d6a..606e9498df462f995b6acac660ee41c9d05a6a61 100644 (file)
@@ -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
 #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", 
@@ -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<Mutex> _(*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<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());
 }
 
 
@@ -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