2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
28 // authority - authorization manager
30 #include "authority.h"
32 #include "connection.h"
36 #include <security_cdsa_utilities/AuthorizationWalkers.h>
38 using Authorization::AuthItemSet
;
39 using Authorization::AuthItemRef
;
40 using Authorization::AuthValue
;
41 using Authorization::AuthValueOverlay
;
44 // The global dictionary of extant AuthorizationTokens
46 AuthorizationToken::AuthMap
AuthorizationToken::authMap
; // set of extant authorizations
47 Mutex
AuthorizationToken::authMapLock
; // lock for mAuthorizations (only)
52 // Create an authorization token.
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())
63 // generate our (random) handle
64 Server::active().random(mHandle
);
66 // register handle in the global map
67 StLock
<Mutex
> _(authMapLock
);
68 authMap
[mHandle
] = this;
71 secdebug("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 secdebug("SSauth", "Authorization %p destroyed", this);
85 Session
&AuthorizationToken::session() const
87 return referent
<Session
>();
92 // Locate an authorization given its blob.
94 AuthorizationToken
&AuthorizationToken::find(const AuthorizationBlob
&blob
)
96 StLock
<Mutex
> _(authMapLock
);
97 AuthMap::iterator it
= authMap
.find(blob
);
98 if (it
== authMap
.end())
99 Authorization::Error::throwMe(errAuthorizationInvalidRef
);
105 // Handle atomic deletion of AuthorizationToken objects
107 AuthorizationToken::Deleter::Deleter(const AuthorizationBlob
&blob
)
110 AuthMap::iterator it
= authMap
.find(blob
);
111 if (it
== authMap
.end())
112 Authorization::Error::throwMe(errAuthorizationInvalidRef
);
116 void AuthorizationToken::Deleter::remove()
119 authMap
.erase(mAuth
->handle());
126 // Given a set of credentials, add it to our private credentials and return the result
128 // must hold Session::mCredsLock
129 CredentialSet
AuthorizationToken::effectiveCreds() const
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())
142 // Add more credential dependencies to an authorization
144 // must hold Session::mCredsLock
145 void AuthorizationToken::mergeCredentials(const CredentialSet
&add
)
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
);
152 secdebug("SSauth", "Authorization %p merged %d new credentials for %d total",
153 this, int(add
.size()), int(mBaseCreds
.size()));
158 // Register a new process that uses this authorization token.
159 // This is an idempotent operation.
161 void AuthorizationToken::addProcess(Process
&proc
)
163 StLock
<Mutex
> _(mLock
);
164 mUsingProcesses
.insert(&proc
);
165 secdebug("SSauth", "Authorization %p added process %p(%d)", this, &proc
, proc
.pid());
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.
175 bool AuthorizationToken::endProcess(Process
&proc
)
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();
187 // Check whether internalization/externalization is allowed
189 bool AuthorizationToken::mayExternalize(Process
&) const
191 return mTransferCount
> 0;
194 bool AuthorizationToken::mayInternalize(Process
&, bool countIt
)
196 StLock
<Mutex
> _(mLock
);
197 if (mTransferCount
> 0) {
200 secdebug("SSauth", "Authorization %p decrement intcount to %d", this, mTransferCount
);
208 AuthorizationToken::infoSet(AuthorizationString tag
)
210 StLock
<Mutex
> _(mLock
); // consider a separate lock
216 AuthItemSet::iterator found
= find_if(mInfoSet
.begin(), mInfoSet
.end(),
217 Authorization::FindAuthItemByRightName(tag
));
218 if (found
!= mInfoSet
.end())
219 tempSet
.insert(AuthItemRef(*found
));
225 secdebug("SSauth", "Authorization %p returning copy of context %s%s.", this, tag
? "for tag " : "", tag
? "" : tag
);
231 AuthorizationToken::setInfoSet(AuthItemSet
&newInfoSet
)
233 StLock
<Mutex
> _(mLock
); // consider a separate lock
234 secdebug("SSauth", "Authorization %p setting new context", this);
235 mInfoSet
= newInfoSet
;
238 // This is destructive (non-merging)
240 AuthorizationToken::setCredentialInfo(const Credential
&inCred
)
242 AuthItemSet dstInfoSet
;
243 char uid_string
[16]; // fit a uid_t(u_int32_t)
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
);
251 AuthItemRef
userHint("username", AuthValueOverlay(inCred
->username()), 0);
252 dstInfoSet
.insert(userHint
);
254 setInfoSet(dstInfoSet
);
258 AuthorizationToken::clearInfoSet()
260 AuthItemSet dstInfoSet
;
261 secdebug("SSauth", "Authorization %p clearing context", this);
262 setInfoSet(dstInfoSet
);