]> git.saurik.com Git - apple/security.git/blob - SecurityServer/authority.cpp
Security-177.tar.gz
[apple/security.git] / SecurityServer / authority.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // authority - authorization manager
21 //
22 #include "authority.h"
23 #include "server.h"
24 #include "connection.h"
25 #include "session.h"
26 #include "process.h"
27
28 #include "AuthorizationWalkers.h"
29
30 using Authorization::AuthItemSet;
31 using Authorization::AuthItemRef;
32 using Authorization::AuthValue;
33 using Authorization::AuthValueOverlay;
34
35 //
36 // The global dictionary of extant AuthorizationTokens
37 //
38 AuthorizationToken::AuthMap AuthorizationToken::authMap; // set of extant authorizations
39 Mutex AuthorizationToken::authMapLock; // lock for mAuthorizations (only)
40
41
42 //
43 // Construct an Authority
44 //
45 Authority::Authority(const char *configFile)
46 : Authorization::Engine(configFile)
47 {
48 }
49
50 Authority::~Authority()
51 {
52 }
53
54
55 //
56 // Create an authorization token.
57 //
58 AuthorizationToken::AuthorizationToken(Session &ssn, const CredentialSet &base, const audit_token_t &auditToken)
59 : session(ssn), mBaseCreds(base), mTransferCount(INT_MAX),
60 mCreatorUid(auditToken.val[1]),
61 mCreatorGid(auditToken.val[2]),
62 mCreatorCode(Server::connection().process.clientCode()),
63 mCreatorPid(Server::connection().process.pid()),
64 mCreatorAuditToken(auditToken)
65 {
66 // generate our (random) handle
67 Server::active().random(mHandle);
68
69 // register handle in the global map
70 StLock<Mutex> _(authMapLock);
71 authMap[mHandle] = this;
72
73 // register with parent session
74 session.addAuthorization(this);
75
76 // all ready
77 secdebug("SSauth", "Authorization %p created using %d credentials; owner=%s",
78 this, int(mBaseCreds.size()),
79 mCreatorCode ? mCreatorCode->encode().c_str() : "unknown");
80 }
81
82 AuthorizationToken::~AuthorizationToken()
83 {
84 // we better be clean
85 assert(mUsingProcesses.empty());
86
87 // deregister from parent session
88 if (session.removeAuthorization(this))
89 delete &session;
90
91 secdebug("SSauth", "Authorization %p destroyed", this);
92 }
93
94
95 //
96 // Locate an authorization given its blob.
97 //
98 AuthorizationToken &AuthorizationToken::find(const AuthorizationBlob &blob)
99 {
100 StLock<Mutex> _(authMapLock);
101 AuthMap::iterator it = authMap.find(blob);
102 if (it == authMap.end())
103 Authorization::Error::throwMe(errAuthorizationInvalidRef);
104 return *it->second;
105 }
106
107
108 //
109 // Handle atomic deletion of AuthorizationToken objects
110 //
111 AuthorizationToken::Deleter::Deleter(const AuthorizationBlob &blob)
112 : lock(authMapLock)
113 {
114 AuthMap::iterator it = authMap.find(blob);
115 if (it == authMap.end())
116 Authorization::Error::throwMe(errAuthorizationInvalidRef);
117 mAuth = it->second;
118 }
119
120 void AuthorizationToken::Deleter::remove()
121 {
122 if (mAuth) {
123 authMap.erase(mAuth->handle());
124 delete mAuth;
125 mAuth = NULL;
126 }
127 }
128
129
130 //
131 // Given a set of credentials, add it to our private credentials and return the result
132 //
133 // must hold Session::mCredsLock
134 CredentialSet AuthorizationToken::effectiveCreds() const
135 {
136 secdebug("SSauth", "Authorization %p grabbing session %p creds %p",
137 this, &session, &session.authCredentials());
138 CredentialSet result = session.authCredentials();
139 for (CredentialSet::const_iterator it = mBaseCreds.begin(); it != mBaseCreds.end(); it++)
140 if (!(*it)->isShared())
141 result.insert(*it);
142 return result;
143 }
144
145
146 //
147 // Add more credential dependencies to an authorization
148 //
149 // must hold Session::mCredsLock
150 void AuthorizationToken::mergeCredentials(const CredentialSet &add)
151 {
152 secdebug("SSauth", "Authorization %p merge creds %p", this, &add);
153 for (CredentialSet::const_iterator it = add.begin(); it != add.end(); it++) {
154 mBaseCreds.erase(*it);
155 mBaseCreds.insert(*it);
156 }
157 secdebug("SSauth", "Authorization %p merged %d new credentials for %d total",
158 this, int(add.size()), int(mBaseCreds.size()));
159 }
160
161
162 //
163 // Register a new process that uses this authorization token.
164 // This is an idempotent operation.
165 //
166 void AuthorizationToken::addProcess(Process &proc)
167 {
168 StLock<Mutex> _(mLock);
169 mUsingProcesses.insert(&proc);
170 secdebug("SSauth", "Authorization %p added process %p(%d)", this, &proc, proc.pid());
171 }
172
173
174 //
175 // Completely unregister client process.
176 // It does not matter how often it was registered with addProcess before.
177 // This returns true if no more processes use this token. Presumably you
178 // would then want to clean up, though that's up to you.
179 //
180 bool AuthorizationToken::endProcess(Process &proc)
181 {
182 StLock<Mutex> _(mLock);
183 assert(mUsingProcesses.find(&proc) != mUsingProcesses.end());
184 mUsingProcesses.erase(&proc);
185 secdebug("SSauth", "Authorization %p removed process %p(%d)%s",
186 this, &proc, proc.pid(), mUsingProcesses.empty() ? " FINAL" : "");
187 return mUsingProcesses.empty();
188 }
189
190
191 //
192 // Check whether internalization/externalization is allowed
193 //
194 bool AuthorizationToken::mayExternalize(Process &) const
195 {
196 return mTransferCount > 0;
197 }
198
199 bool AuthorizationToken::mayInternalize(Process &, bool countIt)
200 {
201 StLock<Mutex> _(mLock);
202 if (mTransferCount > 0) {
203 if (countIt) {
204 mTransferCount--;
205 secdebug("SSauth", "Authorization %p decrement intcount to %d", this, mTransferCount);
206 }
207 return true;
208 }
209 return false;
210 }
211
212 AuthItemSet
213 AuthorizationToken::infoSet(AuthorizationString tag)
214 {
215 StLock<Mutex> _(mLock); // consider a separate lock
216
217 AuthItemSet tempSet;
218
219 if (tag)
220 {
221 AuthItemSet::iterator found = find_if(mInfoSet.begin(), mInfoSet.end(),
222 Authorization::FindAuthItemByRightName(tag));
223 if (found != mInfoSet.end())
224 tempSet.insert(AuthItemRef(*found));
225
226 }
227 else
228 tempSet = mInfoSet;
229
230 secdebug("SSauth", "Authorization %p returning copy of context %s%s.", this, tag ? "for tag " : "", tag ? "" : tag);
231
232 return tempSet;
233 }
234
235 void
236 AuthorizationToken::setInfoSet(AuthItemSet &newInfoSet)
237 {
238 StLock<Mutex> _(mLock); // consider a separate lock
239 secdebug("SSauth", "Authorization %p setting new context", this);
240 mInfoSet = newInfoSet;
241 }
242
243 // This is destructive (non-merging)
244 void
245 AuthorizationToken::setCredentialInfo(const Credential &inCred)
246 {
247 AuthItemSet dstInfoSet;
248 char uid_string[16]; // fit a uid_t(u_int32_t)
249
250 if (snprintf(uid_string, sizeof(uid_string), "%u", inCred->uid()) >=
251 int(sizeof(uid_string)))
252 uid_string[0] = '\0';
253 AuthItemRef uidHint("uid", AuthValueOverlay(uid_string ? strlen(uid_string) + 1 : 0, uid_string), 0);
254 dstInfoSet.insert(uidHint);
255
256 AuthItemRef userHint("username", AuthValueOverlay(inCred->username()), 0);
257 dstInfoSet.insert(userHint);
258
259 setInfoSet(dstInfoSet);
260 }
261
262 void
263 AuthorizationToken::clearInfoSet()
264 {
265 AuthItemSet dstInfoSet;
266 secdebug("SSauth", "Authorization %p clearing context", this);
267 setInfoSet(dstInfoSet);
268 }
269