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();