2  * Copyright (c) 2000-2009,2012 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  26 // process - track a single client process and its belongings 
  31 #include "tempdatabase.h" 
  32 #include "child.h"          // ServerChild (really UnixPlusPlus::Child)::find() 
  34 #include <security_utilities/ccaudit.h> 
  35 #include <security_utilities/logging.h> //@@@ debug only 
  36 #include "agentquery.h" 
  40 // Construct a Process object. 
  42 Process::Process(TaskPort taskPort
,     const ClientSetupInfo 
*info
, const CommonCriteria::AuditToken 
&audit
) 
  43  :  mTaskPort(taskPort
), mByteFlipped(false), mPid(audit
.pid()), mUid(audit
.euid()), mGid(audit
.egid()), mAudit(audit
) 
  45         StLock
<Mutex
> _(*this); 
  46     xpc_transaction_begin(); 
  48         parent(Session::find(audit
.sessionId(), true)); 
  50         // let's take a look at our wannabe client... 
  52         // Not enough to make sure we will get the right process, as 
  53         // pids get recycled. But we will later create the actual SecCode using 
  54         // the audit token, which is unique to the one instance of the process, 
  55         // so this just catches a pid mismatch early. 
  56         if (mTaskPort
.pid() != mPid
) { 
  57                 secnotice("SecServer", "Task/pid setup mismatch pid=%d task=%d(%d)", 
  58                                   mPid
, mTaskPort
.port(), mTaskPort
.pid()); 
  59                 CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED
);     // you lied! 
  63         ClientIdentification::setup(this->audit_token()); 
  66                 // This can happen if the process died in the meantime. 
  67                 secnotice("SecServer", "no process created in setup, old pid=%d old task=%d(%d)", 
  68                                   mPid
, mTaskPort
.port(), mTaskPort
.pid()); 
  69                 CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED
); 
  72         // This is a "retain", matched by the deallocate call in ~Process 
  73         mTaskPort
.modRefs(MACH_PORT_RIGHT_SEND
, 1); 
  75     // NB: ServerChild::find() should only be used to determine 
  76     // *existence*.  Don't use the returned Child object for anything else,  
  77     // as it is not protected against its underlying process's destruction.   
  78         if (this->pid() == getpid() // called ourselves (through some API). Do NOT record this as a "dirty" transaction 
  79         || ServerChild::find
<ServerChild
>(this->pid()))   // securityd's child; do not mark this txn dirty 
  80         xpc_transaction_end(); 
  82     secinfo("SecServer", "%p client new: pid:%d session:%d %s taskPort:%d uid:%d gid:%d", this, this->pid(), this->session().sessionId(), 
  83              (char *)codePath(this->processCode()).c_str(), taskPort
.port(), mUid
, mGid
); 
  88 // Screen a process setup request for an existing process. 
  89 // This means the client has requested intialization even though we remember having 
  90 // talked to it in the past. This could either be an exec(2), or the client could just 
  91 // have forgotten all about its securityd client state. Or it could be an attack... 
  93 void Process::reset(TaskPort taskPort
, const ClientSetupInfo 
*info
, const CommonCriteria::AuditToken 
&audit
) 
  95         StLock
<Mutex
> _(*this); 
  96         if (taskPort 
!= mTaskPort
) { 
  97                 secnotice("SecServer", "Process %p(%d) reset mismatch (tp %d-%d)", 
  98                         this, pid(), taskPort
.port(), mTaskPort
.port()); 
  99                 //@@@ CssmError::throwMe(CSSM_ERRCODE_VERIFICATION_FAILURE);            // liar 
 102         CFCopyRef
<SecCodeRef
> oldCode 
= processCode(); 
 104         ClientIdentification::setup(this->audit_token());       // re-constructs processCode() 
 105         if (CFEqual(oldCode
, processCode())) { 
 106         secnotice("SecServer", "%p Client reset amnesia", this); 
 108         secnotice("SecServer", "%p Client reset full", this); 
 114 // Common set processing 
 116 void Process::setup(const ClientSetupInfo 
*info
) 
 118         // process setup info 
 121         if (info
->order 
== 0x1234) {    // right side up 
 122                 pversion 
= info
->version
; 
 123                 mByteFlipped 
= false; 
 124         } else if (info
->order 
== 0x34120000) { // flip side up 
 125                 pversion 
= flip(info
->version
); 
 127         } else // non comprende 
 128                 CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION
); 
 130         // check wire protocol version 
 131         if (pversion 
!= SSPROTOVERSION
) 
 132                 CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION
); 
 137 // Clean up a Process object 
 141     secinfo("SecServer", "%p client release: %d", this, this->pid()); 
 143     // release our name for the process's task port 
 145         mTaskPort
.deallocate(); 
 147     xpc_transaction_end(); 
 152         StLock
<Mutex
> _(*this); 
 154         // release local temp store 
 157         // standard kill processing 
 162 Session
& Process::session() const 
 164         return parent
<Session
>(); 
 168 void Process::checkSession(const audit_token_t 
&auditToken
) 
 170         Security::CommonCriteria::AuditToken 
audit(auditToken
); 
 171         if (audit
.sessionId() != this->session().sessionId()) 
 172                 this->changeSession(audit
.sessionId()); 
 176 LocalDatabase 
&Process::localStore() 
 178         StLock
<Mutex
> _(*this); 
 180                 mLocalStore 
= new TempDatabase(*this); 
 184 Key 
*Process::makeTemporaryKey(const CssmKey 
&key
, CSSM_KEYATTR_FLAGS moreAttributes
, 
 185         const AclEntryPrototype 
*owner
) 
 187         return safer_cast
<TempDatabase
&>(localStore()).makeKey(key
, moreAttributes
, owner
); 
 192 // Change the session of a process. 
 193 // This is the result of SessionCreate from a known process client. 
 195 void Process::changeSession(Session::SessionId sessionId
) 
 198         parent(Session::find(sessionId
, true)); 
 199     secnotice("SecServer", "%p client change session to %d", this, this->session().sessionId()); 
 204 // Debug dump support 
 206 #if defined(DEBUGDUMP) 
 208 void Process::dumpNode() 
 210         PerProcess::dumpNode(); 
 212                 Debug::dump(" FLIPPED"); 
 213         Debug::dump(" task=%d pid=%d uid/gid=%d/%d", 
 214                 mTaskPort
.port(), mPid
, mUid
, mGid
); 
 215         ClientIdentification::dump();