]>
Commit | Line | Data |
---|---|---|
d8f41ccd A |
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" | |
d8f41ccd A |
32 | #include "child.h" // ServerChild (really UnixPlusPlus::Child)::find() |
33 | ||
fa7225c8 | 34 | #include <security_utilities/ccaudit.h> |
d8f41ccd A |
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) | |
dbe77505 | 43 | : mTaskPort(taskPort), mByteFlipped(false), mPid(audit.pid()), mUid(audit.euid()), mGid(audit.egid()), mAudit(audit) |
d8f41ccd A |
44 | { |
45 | StLock<Mutex> _(*this); | |
b54c578e | 46 | xpc_transaction_begin(); |
d8f41ccd A |
47 | // set parent session |
48 | parent(Session::find(audit.sessionId(), true)); | |
dbe77505 A |
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. | |
d8f41ccd | 56 | if (mTaskPort.pid() != mPid) { |
79b9da22 | 57 | secnotice("SecServer", "Task/pid setup mismatch pid=%d task=%d(%d)", |
dbe77505 | 58 | mPid, mTaskPort.port(), mTaskPort.pid()); |
d8f41ccd A |
59 | CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); // you lied! |
60 | } | |
dbe77505 | 61 | |
d8f41ccd | 62 | setup(info); |
dbe77505 A |
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 | ||
d64be36e A |
72 | // This is a "retain", matched by the deallocate call in ~Process |
73 | mTaskPort.modRefs(MACH_PORT_RIGHT_SEND, 1); | |
74 | ||
d8f41ccd A |
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 | |
b54c578e | 80 | xpc_transaction_end(); |
d8f41ccd | 81 | |
79b9da22 | 82 | secinfo("SecServer", "%p client new: pid:%d session:%d %s taskPort:%d uid:%d gid:%d", this, this->pid(), this->session().sessionId(), |
fa7225c8 | 83 | (char *)codePath(this->processCode()).c_str(), taskPort.port(), mUid, mGid); |
d8f41ccd A |
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) { | |
79b9da22 | 97 | secnotice("SecServer", "Process %p(%d) reset mismatch (tp %d-%d)", |
d8f41ccd A |
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 | ||
dbe77505 | 104 | ClientIdentification::setup(this->audit_token()); // re-constructs processCode() |
d8f41ccd | 105 | if (CFEqual(oldCode, processCode())) { |
79b9da22 | 106 | secnotice("SecServer", "%p Client reset amnesia", this); |
d8f41ccd | 107 | } else { |
79b9da22 | 108 | secnotice("SecServer", "%p Client reset full", this); |
d8f41ccd A |
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 | { | |
79b9da22 | 141 | secinfo("SecServer", "%p client release: %d", this, this->pid()); |
fa7225c8 | 142 | |
d8f41ccd | 143 | // release our name for the process's task port |
dbe77505 A |
144 | if (mTaskPort) { |
145 | mTaskPort.deallocate(); | |
146 | } | |
b54c578e | 147 | xpc_transaction_end(); |
d8f41ccd A |
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 | { | |
fa7225c8 | 170 | Security::CommonCriteria::AuditToken audit(auditToken); |
d8f41ccd A |
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)); | |
79b9da22 | 199 | secnotice("SecServer", "%p client change session to %d", this, this->session().sessionId()); |
d8f41ccd A |
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); | |
d8f41ccd A |
215 | ClientIdentification::dump(); |
216 | } | |
217 | ||
218 | #endif //DEBUGDUMP |