2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 // authority - authorization manager
28 #include "authority.h"
30 #include "connection.h"
34 #include <security_cdsa_utilities/AuthorizationWalkers.h>
36 #include <security_utilities/ccaudit.h> // AuditToken
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 //@@@ Workaround ONLY! Don't destruct this map on termination
48 AuthorizationToken::AuthMap
&AuthorizationToken::authMap
= *new AuthMap
; // set of extant authorizations
49 Mutex
AuthorizationToken::authMapLock
; // lock for mAuthorizations (only)
54 // Create an authorization token.
56 AuthorizationToken::AuthorizationToken(Session
&ssn
, const CredentialSet
&base
,
57 const audit_token_t
&auditToken
)
58 : mBaseCreds(base
), mTransferCount(INT_MAX
),
59 mCreatorCode(Server::process().clientCode()),
60 mCreatorPid(Server::process().pid()),
61 mCreatorAuditToken(auditToken
)
63 mCreatorUid
= mCreatorAuditToken
.euid();
64 mCreatorGid
= mCreatorAuditToken
.egid();
69 // generate our (random) handle
70 Server::active().random(mHandle
);
72 // register handle in the global map
73 StLock
<Mutex
> _(authMapLock
);
74 authMap
[mHandle
] = this;
77 secdebug("SSauth", "Authorization %p created using %d credentials; owner=%s",
78 this, int(mBaseCreds
.size()),
79 mCreatorCode
? mCreatorCode
->encode().c_str() : "unknown");
82 AuthorizationToken::~AuthorizationToken()
85 assert(mUsingProcesses
.empty());
87 secdebug("SSauth", "Authorization %p destroyed", this);
91 Session
&AuthorizationToken::session() const
93 return referent
<Session
>();
98 // Locate an authorization given its blob.
100 AuthorizationToken
&AuthorizationToken::find(const AuthorizationBlob
&blob
)
102 StLock
<Mutex
> _(authMapLock
);
103 AuthMap::iterator it
= authMap
.find(blob
);
104 if (it
== authMap
.end())
105 Authorization::Error::throwMe(errAuthorizationInvalidRef
);
111 // Handle atomic deletion of AuthorizationToken objects
113 AuthorizationToken::Deleter::Deleter(const AuthorizationBlob
&blob
)
116 AuthMap::iterator it
= authMap
.find(blob
);
117 if (it
== authMap
.end())
118 Authorization::Error::throwMe(errAuthorizationInvalidRef
);
122 void AuthorizationToken::Deleter::remove()
125 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 secdebug("SSauth", "Authorization %p grabbing session %p creds %p",
138 this, &session(), &session().authCredentials());
139 CredentialSet result
= session().authCredentials();
140 for (CredentialSet::const_iterator it
= mBaseCreds
.begin(); it
!= mBaseCreds
.end(); it
++)
141 if (!(*it
)->isShared())
148 // Add more credential dependencies to an authorization
150 // must hold Session::mCredsLock
151 void AuthorizationToken::mergeCredentials(const CredentialSet
&add
)
153 secdebug("SSauth", "Authorization %p merge creds %p", this, &add
);
154 for (CredentialSet::const_iterator it
= add
.begin(); it
!= add
.end(); it
++) {
155 mBaseCreds
.erase(*it
);
156 mBaseCreds
.insert(*it
);
158 secdebug("SSauth", "Authorization %p merged %d new credentials for %d total",
159 this, int(add
.size()), int(mBaseCreds
.size()));
164 // Register a new process that uses this authorization token.
165 // This is an idempotent operation.
167 void AuthorizationToken::addProcess(Process
&proc
)
169 StLock
<Mutex
> _(mLock
);
170 mUsingProcesses
.insert(&proc
);
171 secdebug("SSauth", "Authorization %p added process %p(%d)", this, &proc
, proc
.pid());
176 // Completely unregister client process.
177 // It does not matter how often it was registered with addProcess before.
178 // This returns true if no more processes use this token. Presumably you
179 // would then want to clean up, though that's up to you.
181 bool AuthorizationToken::endProcess(Process
&proc
)
183 StLock
<Mutex
> _(mLock
);
184 assert(mUsingProcesses
.find(&proc
) != mUsingProcesses
.end());
185 mUsingProcesses
.erase(&proc
);
186 secdebug("SSauth", "Authorization %p removed process %p(%d)%s",
187 this, &proc
, proc
.pid(), mUsingProcesses
.empty() ? " FINAL" : "");
188 return mUsingProcesses
.empty();
193 // Check whether internalization/externalization is allowed
195 bool AuthorizationToken::mayExternalize(Process
&) const
197 return mTransferCount
> 0;
200 bool AuthorizationToken::mayInternalize(Process
&, bool countIt
)
202 StLock
<Mutex
> _(mLock
);
203 if (mTransferCount
> 0) {
206 secdebug("SSauth", "Authorization %p decrement intcount to %d", this, mTransferCount
);
214 AuthorizationToken::infoSet(AuthorizationString tag
)
216 StLock
<Mutex
> _(mLock
); // consider a separate lock
222 AuthItemSet::iterator found
= find_if(mInfoSet
.begin(), mInfoSet
.end(),
223 Authorization::FindAuthItemByRightName(tag
));
224 if (found
!= mInfoSet
.end())
225 tempSet
.insert(AuthItemRef(*found
));
231 secdebug("SSauth", "Authorization %p returning copy of context %s%s.", this, tag
? "for tag " : "", tag
? "" : tag
);
237 AuthorizationToken::setInfoSet(AuthItemSet
&newInfoSet
)
239 StLock
<Mutex
> _(mLock
); // consider a separate lock
240 secdebug("SSauth", "Authorization %p setting new context", this);
241 mInfoSet
= newInfoSet
;
244 // This is destructive (non-merging)
246 AuthorizationToken::setCredentialInfo(const Credential
&inCred
)
248 AuthItemSet dstInfoSet
;
249 char uid_string
[16]; // fit a uid_t(u_int32_t)
251 if (snprintf(uid_string
, sizeof(uid_string
), "%u", inCred
->uid()) >=
252 int(sizeof(uid_string
)))
253 uid_string
[0] = '\0';
254 AuthItemRef
uidHint("uid", AuthValueOverlay(uid_string
? strlen(uid_string
) + 1 : 0, uid_string
), 0);
255 dstInfoSet
.insert(uidHint
);
257 AuthItemRef
userHint("username", AuthValueOverlay(inCred
->username()), 0);
258 dstInfoSet
.insert(userHint
);
260 setInfoSet(dstInfoSet
);
264 AuthorizationToken::clearInfoSet()
266 AuthItemSet dstInfoSet
;
267 secdebug("SSauth", "Authorization %p clearing context", this);
268 setInfoSet(dstInfoSet
);
272 AuthorizationToken::scrubInfoSet()
274 AuthItemSet srcInfoSet
= infoSet(), dstInfoSet
;
275 AuthItemSet::const_iterator end
= srcInfoSet
.end();
276 for (AuthItemSet::const_iterator it
= srcInfoSet
.begin(); it
!= end
; ++it
)
278 const AuthItemRef
&item
= *it
;
279 if (item
->flags() == kAuthorizationContextFlagExtractable
)
280 dstInfoSet
.insert(item
);
282 secdebug("SSauth", "Authorization %p scrubbing context", this);
283 setInfoSet(dstInfoSet
);