]>
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) | |
43 | : mTaskPort(taskPort), mByteFlipped(false), mPid(audit.pid()), mUid(audit.euid()), mGid(audit.egid()) | |
44 | { | |
45 | StLock<Mutex> _(*this); | |
46 | ||
47 | // set parent session | |
48 | parent(Session::find(audit.sessionId(), true)); | |
49 | ||
50 | // let's take a look at our wannabe client... | |
51 | if (mTaskPort.pid() != mPid) { | |
fa7225c8 | 52 | secnotice("SS", "Task/pid setup mismatch pid=%d task=%d(%d)", |
d8f41ccd A |
53 | mPid, mTaskPort.port(), mTaskPort.pid()); |
54 | CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); // you lied! | |
55 | } | |
56 | ||
57 | setup(info); | |
58 | ClientIdentification::setup(this->pid()); | |
59 | ||
60 | // NB: ServerChild::find() should only be used to determine | |
61 | // *existence*. Don't use the returned Child object for anything else, | |
62 | // as it is not protected against its underlying process's destruction. | |
63 | if (this->pid() == getpid() // called ourselves (through some API). Do NOT record this as a "dirty" transaction | |
64 | || ServerChild::find<ServerChild>(this->pid())) // securityd's child; do not mark this txn dirty | |
65 | VProc::Transaction::deactivate(); | |
66 | ||
b04fe171 | 67 | secinfo("SS", "%p client new: pid:%d session:%d %s taskPort:%d uid:%d gid:%d", this, this->pid(), this->session().sessionId(), |
fa7225c8 | 68 | (char *)codePath(this->processCode()).c_str(), taskPort.port(), mUid, mGid); |
d8f41ccd A |
69 | } |
70 | ||
71 | ||
72 | // | |
73 | // Screen a process setup request for an existing process. | |
74 | // This means the client has requested intialization even though we remember having | |
75 | // talked to it in the past. This could either be an exec(2), or the client could just | |
76 | // have forgotten all about its securityd client state. Or it could be an attack... | |
77 | // | |
78 | void Process::reset(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit) | |
79 | { | |
80 | StLock<Mutex> _(*this); | |
81 | if (taskPort != mTaskPort) { | |
fa7225c8 | 82 | secnotice("SS", "Process %p(%d) reset mismatch (tp %d-%d)", |
d8f41ccd A |
83 | this, pid(), taskPort.port(), mTaskPort.port()); |
84 | //@@@ CssmError::throwMe(CSSM_ERRCODE_VERIFICATION_FAILURE); // liar | |
85 | } | |
86 | setup(info); | |
87 | CFCopyRef<SecCodeRef> oldCode = processCode(); | |
88 | ||
89 | ClientIdentification::setup(this->pid()); // re-constructs processCode() | |
90 | if (CFEqual(oldCode, processCode())) { | |
fa7225c8 | 91 | secnotice("SS", "%p Client reset amnesia", this); |
d8f41ccd | 92 | } else { |
fa7225c8 | 93 | secnotice("SS", "%p Client reset full", this); |
d8f41ccd A |
94 | CodeSigningHost::reset(); |
95 | } | |
96 | } | |
97 | ||
98 | ||
99 | // | |
100 | // Common set processing | |
101 | // | |
102 | void Process::setup(const ClientSetupInfo *info) | |
103 | { | |
104 | // process setup info | |
105 | assert(info); | |
106 | uint32 pversion; | |
107 | if (info->order == 0x1234) { // right side up | |
108 | pversion = info->version; | |
109 | mByteFlipped = false; | |
110 | } else if (info->order == 0x34120000) { // flip side up | |
111 | pversion = flip(info->version); | |
112 | mByteFlipped = true; | |
113 | } else // non comprende | |
114 | CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); | |
115 | ||
116 | // check wire protocol version | |
117 | if (pversion != SSPROTOVERSION) | |
118 | CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); | |
119 | } | |
120 | ||
121 | ||
122 | // | |
123 | // Clean up a Process object | |
124 | // | |
125 | Process::~Process() | |
126 | { | |
b04fe171 | 127 | secinfo("SS", "%p client release: %d", this, this->pid()); |
fa7225c8 | 128 | |
d8f41ccd A |
129 | // release our name for the process's task port |
130 | if (mTaskPort) | |
131 | mTaskPort.destroy(); | |
132 | } | |
133 | ||
134 | void Process::kill() | |
135 | { | |
136 | StLock<Mutex> _(*this); | |
137 | ||
138 | // release local temp store | |
139 | mLocalStore = NULL; | |
140 | ||
141 | // standard kill processing | |
142 | PerProcess::kill(); | |
143 | } | |
144 | ||
145 | ||
146 | Session& Process::session() const | |
147 | { | |
148 | return parent<Session>(); | |
149 | } | |
150 | ||
151 | ||
152 | void Process::checkSession(const audit_token_t &auditToken) | |
153 | { | |
fa7225c8 | 154 | Security::CommonCriteria::AuditToken audit(auditToken); |
d8f41ccd A |
155 | if (audit.sessionId() != this->session().sessionId()) |
156 | this->changeSession(audit.sessionId()); | |
157 | } | |
158 | ||
159 | ||
160 | LocalDatabase &Process::localStore() | |
161 | { | |
162 | StLock<Mutex> _(*this); | |
163 | if (!mLocalStore) | |
164 | mLocalStore = new TempDatabase(*this); | |
165 | return *mLocalStore; | |
166 | } | |
167 | ||
168 | Key *Process::makeTemporaryKey(const CssmKey &key, CSSM_KEYATTR_FLAGS moreAttributes, | |
169 | const AclEntryPrototype *owner) | |
170 | { | |
171 | return safer_cast<TempDatabase&>(localStore()).makeKey(key, moreAttributes, owner); | |
172 | } | |
173 | ||
174 | ||
175 | // | |
176 | // Change the session of a process. | |
177 | // This is the result of SessionCreate from a known process client. | |
178 | // | |
179 | void Process::changeSession(Session::SessionId sessionId) | |
180 | { | |
181 | // re-parent | |
182 | parent(Session::find(sessionId, true)); | |
fa7225c8 | 183 | secnotice("SS", "%p client change session to %d", this, this->session().sessionId()); |
d8f41ccd A |
184 | } |
185 | ||
186 | ||
187 | // | |
188 | // Debug dump support | |
189 | // | |
190 | #if defined(DEBUGDUMP) | |
191 | ||
192 | void Process::dumpNode() | |
193 | { | |
194 | PerProcess::dumpNode(); | |
195 | if (mByteFlipped) | |
196 | Debug::dump(" FLIPPED"); | |
197 | Debug::dump(" task=%d pid=%d uid/gid=%d/%d", | |
198 | mTaskPort.port(), mPid, mUid, mGid); | |
199 | CodeSigningHost::dump(); | |
200 | ClientIdentification::dump(); | |
201 | } | |
202 | ||
203 | #endif //DEBUGDUMP |