]> git.saurik.com Git - apple/security.git/blob - SecurityServer/authority.cpp
Security-164.1.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 security_token_t &securityToken)
59 : session(ssn), mBaseCreds(base), mTransferCount(INT_MAX),
60 mCreatorUid(securityToken.val[0]),
61 mCreatorCode(Server::connection().process.clientCode()),
62 mCreatorPid(Server::connection().process.pid())
63 {
64 // generate our (random) handle
65 Server::active().random(mHandle);
66
67 // register handle in the global map
68 StLock<Mutex> _(authMapLock);
69 authMap[mHandle] = this;
70
71 // register with parent session
72 session.addAuthorization(this);
73
74 // all ready
75 secdebug("SSauth", "Authorization %p created using %d credentials; owner=%s",
76 this, int(mBaseCreds.size()),
77 mCreatorCode ? mCreatorCode->encode().c_str() : "unknown");
78 }
79
80 AuthorizationToken::~AuthorizationToken()
81 {
82 // we better be clean
83 assert(mUsingProcesses.empty());
84
85 // deregister from parent session
86 if (session.removeAuthorization(this))
87 delete &session;
88
89 secdebug("SSauth", "Authorization %p destroyed", this);
90 }
91
92
93 //
94 // Locate an authorization given its blob.
95 //
96 AuthorizationToken &AuthorizationToken::find(const AuthorizationBlob &blob)
97 {
98 StLock<Mutex> _(authMapLock);
99 AuthMap::iterator it = authMap.find(blob);
100 if (it == authMap.end())
101 Authorization::Error::throwMe(errAuthorizationInvalidRef);
102 return *it->second;
103 }
104
105
106 //
107 // Handle atomic deletion of AuthorizationToken objects
108 //
109 AuthorizationToken::Deleter::Deleter(const AuthorizationBlob &blob)
110 : lock(authMapLock)
111 {
112 AuthMap::iterator it = authMap.find(blob);
113 if (it == authMap.end())
114 Authorization::Error::throwMe(errAuthorizationInvalidRef);
115 mAuth = it->second;
116 }
117
118 void AuthorizationToken::Deleter::remove()
119 {
120 if (mAuth) {
121 authMap.erase(mAuth->handle());
122 delete mAuth;
123 mAuth = NULL;
124 }
125 }
126
127
128 //
129 // Given a set of credentials, add it to our private credentials and return the result
130 //
131 // must hold Session::mCredsLock
132 CredentialSet AuthorizationToken::effectiveCreds() const
133 {
134 secdebug("SSauth", "Authorization %p grabbing session %p creds %p",
135 this, &session, &session.authCredentials());
136 CredentialSet result = session.authCredentials();
137 for (CredentialSet::const_iterator it = mBaseCreds.begin(); it != mBaseCreds.end(); it++)
138 if (!(*it)->isShared())
139 result.insert(*it);
140 return result;
141 }
142
143
144 //
145 // Add more credential dependencies to an authorization
146 //
147 // must hold Session::mCredsLock
148 void AuthorizationToken::mergeCredentials(const CredentialSet &add)
149 {
150 secdebug("SSauth", "Authorization %p merge creds %p", this, &add);
151 for (CredentialSet::const_iterator it = add.begin(); it != add.end(); it++) {
152 mBaseCreds.erase(*it);
153 mBaseCreds.insert(*it);
154 }
155 secdebug("SSauth", "Authorization %p merged %d new credentials for %d total",
156 this, int(add.size()), int(mBaseCreds.size()));
157 }
158
159
160 //
161 // Register a new process that uses this authorization token.
162 // This is an idempotent operation.
163 //
164 void AuthorizationToken::addProcess(Process &proc)
165 {
166 StLock<Mutex> _(mLock);
167 mUsingProcesses.insert(&proc);
168 secdebug("SSauth", "Authorization %p added process %p(%d)", this, &proc, proc.pid());
169 }
170
171
172 //
173 // Completely unregister client process.
174 // It does not matter how often it was registered with addProcess before.
175 // This returns true if no more processes use this token. Presumably you
176 // would then want to clean up, though that's up to you.
177 //
178 bool AuthorizationToken::endProcess(Process &proc)
179 {
180 StLock<Mutex> _(mLock);
181 assert(mUsingProcesses.find(&proc) != mUsingProcesses.end());
182 mUsingProcesses.erase(&proc);
183 secdebug("SSauth", "Authorization %p removed process %p(%d)%s",
184 this, &proc, proc.pid(), mUsingProcesses.empty() ? " FINAL" : "");
185 return mUsingProcesses.empty();
186 }
187
188
189 //
190 // Check whether internalization/externalization is allowed
191 //
192 bool AuthorizationToken::mayExternalize(Process &) const
193 {
194 return mTransferCount > 0;
195 }
196
197 bool AuthorizationToken::mayInternalize(Process &, bool countIt)
198 {
199 StLock<Mutex> _(mLock);
200 if (mTransferCount > 0) {
201 if (countIt) {
202 mTransferCount--;
203 secdebug("SSauth", "Authorization %p decrement intcount to %d", this, mTransferCount);
204 }
205 return true;
206 }
207 return false;
208 }
209
210 AuthItemSet
211 AuthorizationToken::infoSet(AuthorizationString tag)
212 {
213 StLock<Mutex> _(mLock); // consider a separate lock
214
215 AuthItemSet tempSet;
216
217 if (tag)
218 {
219 AuthItemSet::iterator found = find_if(mInfoSet.begin(), mInfoSet.end(),
220 Authorization::FindAuthItemByRightName(tag));
221 if (found != mInfoSet.end())
222 tempSet.insert(AuthItemRef(*found));
223
224 }
225 else
226 tempSet = mInfoSet;
227
228 secdebug("SSauth", "Authorization %p returning copy of context %s%s.", this, tag ? "for tag " : "", tag ? "" : tag);
229
230 return tempSet;
231 }
232
233 void
234 AuthorizationToken::setInfoSet(AuthItemSet &newInfoSet)
235 {
236 StLock<Mutex> _(mLock); // consider a separate lock
237 secdebug("SSauth", "Authorization %p setting new context", this);
238 mInfoSet = newInfoSet;
239 }
240
241 // This is destructive (non-merging)
242 void
243 AuthorizationToken::setCredentialInfo(const Credential &inCred)
244 {
245 AuthItemSet dstInfoSet;
246 char uid_string[16]; // fit a uid_t(u_int32_t)
247
248 if (snprintf(uid_string, sizeof(uid_string), "%u", inCred->uid()) >=
249 int(sizeof(uid_string)))
250 uid_string[0] = '\0';
251 AuthItemRef uidHint("uid", AuthValueOverlay(uid_string ? strlen(uid_string) + 1 : 0, uid_string), 0);
252 dstInfoSet.insert(uidHint);
253
254 AuthItemRef userHint("username", AuthValueOverlay(inCred->username()), 0);
255 dstInfoSet.insert(userHint);
256
257 setInfoSet(dstInfoSet);
258 }
259