]> git.saurik.com Git - apple/security.git/blob - securityd/src/process.cpp
Security-59754.41.1.tar.gz
[apple/security.git] / securityd / src / process.cpp
1 /*
2 * Copyright (c) 2000-2009,2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // process - track a single client process and its belongings
27 //
28 #include "process.h"
29 #include "server.h"
30 #include "session.h"
31 #include "tempdatabase.h"
32 #include "child.h" // ServerChild (really UnixPlusPlus::Child)::find()
33
34 #include <security_utilities/ccaudit.h>
35 #include <security_utilities/logging.h> //@@@ debug only
36 #include "agentquery.h"
37
38
39 //
40 // Construct a Process object.
41 //
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)
44 {
45 StLock<Mutex> _(*this);
46 xpc_transaction_begin();
47 // set parent session
48 parent(Session::find(audit.sessionId(), true));
49
50 // let's take a look at our wannabe client...
51
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!
60 }
61
62 setup(info);
63 ClientIdentification::setup(this->audit_token());
64
65 if(!processCode()) {
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);
70 }
71
72 // This is a "retain", matched by the deallocate call in ~Process
73 mTaskPort.modRefs(MACH_PORT_RIGHT_SEND, 1);
74
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();
81
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);
84 }
85
86
87 //
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...
92 //
93 void Process::reset(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit)
94 {
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
100 }
101 setup(info);
102 CFCopyRef<SecCodeRef> oldCode = processCode();
103
104 ClientIdentification::setup(this->audit_token()); // re-constructs processCode()
105 if (CFEqual(oldCode, processCode())) {
106 secnotice("SecServer", "%p Client reset amnesia", this);
107 } else {
108 secnotice("SecServer", "%p Client reset full", this);
109 }
110 }
111
112
113 //
114 // Common set processing
115 //
116 void Process::setup(const ClientSetupInfo *info)
117 {
118 // process setup info
119 assert(info);
120 uint32 pversion;
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);
126 mByteFlipped = true;
127 } else // non comprende
128 CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION);
129
130 // check wire protocol version
131 if (pversion != SSPROTOVERSION)
132 CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION);
133 }
134
135
136 //
137 // Clean up a Process object
138 //
139 Process::~Process()
140 {
141 secinfo("SecServer", "%p client release: %d", this, this->pid());
142
143 // release our name for the process's task port
144 if (mTaskPort) {
145 mTaskPort.deallocate();
146 }
147 xpc_transaction_end();
148 }
149
150 void Process::kill()
151 {
152 StLock<Mutex> _(*this);
153
154 // release local temp store
155 mLocalStore = NULL;
156
157 // standard kill processing
158 PerProcess::kill();
159 }
160
161
162 Session& Process::session() const
163 {
164 return parent<Session>();
165 }
166
167
168 void Process::checkSession(const audit_token_t &auditToken)
169 {
170 Security::CommonCriteria::AuditToken audit(auditToken);
171 if (audit.sessionId() != this->session().sessionId())
172 this->changeSession(audit.sessionId());
173 }
174
175
176 LocalDatabase &Process::localStore()
177 {
178 StLock<Mutex> _(*this);
179 if (!mLocalStore)
180 mLocalStore = new TempDatabase(*this);
181 return *mLocalStore;
182 }
183
184 Key *Process::makeTemporaryKey(const CssmKey &key, CSSM_KEYATTR_FLAGS moreAttributes,
185 const AclEntryPrototype *owner)
186 {
187 return safer_cast<TempDatabase&>(localStore()).makeKey(key, moreAttributes, owner);
188 }
189
190
191 //
192 // Change the session of a process.
193 // This is the result of SessionCreate from a known process client.
194 //
195 void Process::changeSession(Session::SessionId sessionId)
196 {
197 // re-parent
198 parent(Session::find(sessionId, true));
199 secnotice("SecServer", "%p client change session to %d", this, this->session().sessionId());
200 }
201
202
203 //
204 // Debug dump support
205 //
206 #if defined(DEBUGDUMP)
207
208 void Process::dumpNode()
209 {
210 PerProcess::dumpNode();
211 if (mByteFlipped)
212 Debug::dump(" FLIPPED");
213 Debug::dump(" task=%d pid=%d uid/gid=%d/%d",
214 mTaskPort.port(), mPid, mUid, mGid);
215 ClientIdentification::dump();
216 }
217
218 #endif //DEBUGDUMP