2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 // authority - authorization manager
22 #include "authority.h"
24 #include "connection.h"
28 #include "AuthorizationWalkers.h"
30 using Authorization::Right
;
33 // The global dictionary of extant AuthorizationTokens
35 AuthorizationToken::AuthMap
AuthorizationToken::authMap
; // set of extant authorizations
36 Mutex
AuthorizationToken::authMapLock
; // lock for mAuthorizations (only)
40 // Construct an Authority
42 Authority::Authority(const char *configFile
)
43 : Authorization::Engine(configFile
)
47 Authority::~Authority()
53 // Create an authorization token.
55 AuthorizationToken::AuthorizationToken(Session
&ssn
, const CredentialSet
&base
)
56 : session(ssn
), mBaseCreds(base
), mTransferCount(INT_MAX
),
57 mCreatorUid(Server::connection().process
.uid()),
58 mCreatorCode(Server::connection().process
.clientCode()), mInfoSet(NULL
)
60 // generate our (random) handle
61 Server::active().random(mHandle
);
63 // register handle in the global map
64 StLock
<Mutex
> _(authMapLock
);
65 authMap
[mHandle
] = this;
67 // register with parent session
68 session
.addAuthorization(this);
71 IFDEBUG(debug("SSauth", "Authorization %p created using %d credentials; owner=%s",
72 this, int(mBaseCreds
.size()),
73 mCreatorCode
? mCreatorCode
->encode().c_str() : "unknown"));
76 AuthorizationToken::~AuthorizationToken()
79 assert(mUsingProcesses
.empty());
81 // deregister from parent session
82 if (session
.removeAuthorization(this))
85 // remove stored context
88 debug("SSauth", "Authorization %p destroying context @%p", this, mInfoSet
);
89 CssmAllocator::standard().free(mInfoSet
); // @@@ switch to sensitive allocator
92 debug("SSauth", "Authorization %p destroyed", this);
97 // Locate an authorization given its blob.
99 AuthorizationToken
&AuthorizationToken::find(const AuthorizationBlob
&blob
)
101 StLock
<Mutex
> _(authMapLock
);
102 AuthMap::iterator it
= authMap
.find(blob
);
103 if (it
== authMap
.end())
104 Authorization::Error::throwMe(errAuthorizationInvalidRef
);
110 // Handle atomic deletion of AuthorizationToken objects
112 AuthorizationToken::Deleter::Deleter(const AuthorizationBlob
&blob
)
115 AuthMap::iterator it
= authMap
.find(blob
);
116 if (it
== authMap
.end())
117 Authorization::Error::throwMe(errAuthorizationInvalidRef
);
121 void AuthorizationToken::Deleter::remove()
124 authMap
.erase(mAuth
->handle());
132 // Given a set of credentials, add it to our private credentials and return the result
134 // must hold Session::mCredsLock
135 CredentialSet
AuthorizationToken::effectiveCreds() const
137 IFDEBUG(debug("SSauth", "Authorization %p grabbing session %p creds %p", 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())
147 // Add more credential dependencies to an authorization
149 // must hold Session::mCredsLock
150 void AuthorizationToken::mergeCredentials(const CredentialSet
&add
)
152 debug("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
);
157 debug("SSauth", "Authorization %p merged %d new credentials for %d total",
158 this, int(add
.size()), int(mBaseCreds
.size()));
163 // Register a new process that uses this authorization token.
164 // This is an idempotent operation.
166 void AuthorizationToken::addProcess(Process
&proc
)
168 StLock
<Mutex
> _(mLock
);
169 mUsingProcesses
.insert(&proc
);
170 debug("SSauth", "Authorization %p added process %p(%d)", this, &proc
, proc
.pid());
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.
180 bool AuthorizationToken::endProcess(Process
&proc
)
182 StLock
<Mutex
> _(mLock
);
183 assert(mUsingProcesses
.find(&proc
) != mUsingProcesses
.end());
184 mUsingProcesses
.erase(&proc
);
185 IFDEBUG(debug("SSauth", "Authorization %p removed process %p(%d)%s",
186 this, &proc
, proc
.pid(), mUsingProcesses
.empty() ? " FINAL" : ""));
187 return mUsingProcesses
.empty();
192 // Check whether internalization/externalization is allowed
194 bool AuthorizationToken::mayExternalize(Process
&) const
196 return mTransferCount
> 0;
199 bool AuthorizationToken::mayInternalize(Process
&, bool countIt
)
201 StLock
<Mutex
> _(mLock
);
202 if (mTransferCount
> 0) {
205 debug("SSauth", "Authorization %p decrement intcount to %d", this, mTransferCount
);
212 AuthorizationItemSet
&
213 AuthorizationToken::infoSet()
215 StLock
<Mutex
> _(mLock
); // consider a separate lock
216 MutableRightSet
tempInfoSet(mInfoSet
); // turn no info into empty set
218 AuthorizationItemSet
*returnSet
= Copier
<AuthorizationItemSet
>(tempInfoSet
, CssmAllocator::standard()).keep();
219 debug("SSauth", "Authorization %p returning context %p", this, returnSet
);
224 AuthorizationToken::setInfoSet(AuthorizationItemSet
&newInfoSet
)
226 StLock
<Mutex
> _(mLock
); // consider a separate lock
228 CssmAllocator::standard().free(mInfoSet
); // @@@ move to sensitive allocator
229 debug("SSauth", "Authorization %p context %p -> %p", this, mInfoSet
, &newInfoSet
);
230 mInfoSet
= &newInfoSet
;
233 // This is destructive (non-merging)
235 AuthorizationToken::setCredentialInfo(const Credential
&inCred
)
237 StLock
<Mutex
> _(mLock
);
239 MutableRightSet dstInfoSet
;
240 char uid_string
[16]; // fit a uid_t(u_int32_t)
242 if (snprintf(uid_string
, sizeof(uid_string
), "%u", inCred
->uid()) >=
244 uid_string
[0] = '\0';
245 Right
uidHint("uid", uid_string
? strlen(uid_string
) + 1 : 0, uid_string
);
246 dstInfoSet
.push_back(uidHint
);
248 const char *user
= inCred
->username().c_str();
249 Right
userHint("username", user
? strlen(user
) + 1 : 0, user
);
250 dstInfoSet
.push_back(userHint
);
252 AuthorizationItemSet
*newInfoSet
= Copier
<AuthorizationItemSet
>(dstInfoSet
, CssmAllocator::standard()).keep();
253 CssmAllocator::standard().free(mInfoSet
); // @@@ move to sensitive allocator
254 mInfoSet
= newInfoSet
;