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