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"
30 // The global dictionary of extant AuthorizationTokens
32 AuthorizationToken::AuthMap
AuthorizationToken::authMap
; // set of extant authorizations
33 Mutex
AuthorizationToken::authMapLock
; // lock for mAuthorizations (only)
37 // Construct an Authority
39 Authority::Authority(const char *configFile
)
40 : Authorization::Engine(configFile
)
44 Authority::~Authority()
50 // Create an authorization token.
52 AuthorizationToken::AuthorizationToken(Session
&ssn
, const CredentialSet
&base
)
53 : session(ssn
), mBaseCreds(base
), mTransferCount(INT_MAX
),
54 mCreatorUid(Server::connection().process
.uid())
56 // generate our (random) handle
57 Server::active().random(mHandle
);
59 // register handle in the global map
60 StLock
<Mutex
> _(authMapLock
);
61 authMap
[mHandle
] = this;
63 // register with parent session
64 session
.addAuthorization(this);
67 debug("SSauth", "Authorization %p created using %d credentials",
68 this, int(mBaseCreds
.size()));
71 AuthorizationToken::~AuthorizationToken()
74 assert(mUsingProcesses
.empty());
76 // deregister from parent session
77 if (session
.removeAuthorization(this))
80 debug("SSauth", "Authorization %p destroyed", this);
85 // Locate an authorization given its blob.
87 AuthorizationToken
&AuthorizationToken::find(const AuthorizationBlob
&blob
)
89 StLock
<Mutex
> _(authMapLock
);
90 AuthMap::iterator it
= authMap
.find(blob
);
91 if (it
== authMap
.end())
92 Authorization::Error::throwMe(errAuthorizationInvalidRef
);
98 // Handle atomic deletion of AuthorizationToken objects
100 AuthorizationToken::Deleter::Deleter(const AuthorizationBlob
&blob
)
103 AuthMap::iterator it
= authMap
.find(blob
);
104 if (it
== authMap
.end())
105 Authorization::Error::throwMe(errAuthorizationInvalidRef
);
109 void AuthorizationToken::Deleter::remove()
112 authMap
.erase(mAuth
->handle());
120 // Given a set of credentials, add it to our private credentials and return the result
122 CredentialSet
AuthorizationToken::effectiveCreds() const
124 CredentialSet result
= session
.authCredentials();
125 for (CredentialSet::const_iterator it
= mBaseCreds
.begin(); it
!= mBaseCreds
.end(); it
++)
126 if (!(*it
)->isShared())
133 // Add more credential dependencies to an authorization
135 void AuthorizationToken::mergeCredentials(const CredentialSet
&add
)
137 for (CredentialSet::const_iterator it
= add
.begin(); it
!= add
.end(); it
++) {
138 mBaseCreds
.erase(*it
);
139 mBaseCreds
.insert(*it
);
141 debug("SSauth", "Authorization %p merged %d new credentials for %d total",
142 this, int(add
.size()), int(mBaseCreds
.size()));
147 // Register a new process that uses this authorization token.
148 // This is an idempotent operation.
150 void AuthorizationToken::addProcess(Process
&proc
)
152 StLock
<Mutex
> _(mLock
);
153 mUsingProcesses
.insert(&proc
);
154 debug("SSauth", "Authorization %p added process %p(%d)", this, &proc
, proc
.pid());
159 // Completely unregister client process.
160 // It does not matter how often it was registered with addProcess before.
161 // This returns true if no more processes use this token. Presumably you
162 // would then want to clean up, though that's up to you.
164 bool AuthorizationToken::endProcess(Process
&proc
)
166 StLock
<Mutex
> _(mLock
);
167 assert(mUsingProcesses
.find(&proc
) != mUsingProcesses
.end());
168 mUsingProcesses
.erase(&proc
);
169 IFDEBUG(debug("SSauth", "Authorization %p removed process %p(%d)%s",
170 this, &proc
, proc
.pid(), mUsingProcesses
.empty() ? " FINAL" : ""));
171 return mUsingProcesses
.empty();
176 // Check whether internalization/externalization is allowed
178 bool AuthorizationToken::mayExternalize(Process
&) const
180 return mTransferCount
> 0;
183 bool AuthorizationToken::mayInternalize(Process
&, bool countIt
)
185 StLock
<Mutex
> _(mLock
);
186 if (mTransferCount
> 0) {
189 debug("SSauth", "Authorization %p decrement intcount to %d", this, mTransferCount
);
197 AuthorizationToken::creatorUid() const
203 // Call the underlying authorize() in a critical region.
204 // The engine code is not thread safe.
207 OSStatus
Authority::authorize(const RightSet
&inRights
,
208 const AuthorizationEnvironment
*environment
,
209 AuthorizationFlags flags
, const CredentialSet
*inCredentials
, CredentialSet
*outCredentials
,
210 MutableRightSet
*outRights
, const AuthorizationToken
&auth
)
212 StLock
<Mutex
> _(mLock
);
213 return Authorization::Engine::authorize(inRights
, environment
,
214 flags
, inCredentials
, outCredentials
, outRights
, auth
);