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::AuthItemSet
;
31 using Authorization::AuthItemRef
;
32 using Authorization::AuthValue
;
33 using Authorization::AuthValueOverlay
;
36 // The global dictionary of extant AuthorizationTokens
38 AuthorizationToken::AuthMap
AuthorizationToken::authMap
; // set of extant authorizations
39 Mutex
AuthorizationToken::authMapLock
; // lock for mAuthorizations (only)
43 // Construct an Authority
45 Authority::Authority(const char *configFile
)
46 : Authorization::Engine(configFile
)
50 Authority::~Authority()
56 // Create an authorization token.
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())
64 // generate our (random) handle
65 Server::active().random(mHandle
);
67 // register handle in the global map
68 StLock
<Mutex
> _(authMapLock
);
69 authMap
[mHandle
] = this;
71 // register with parent session
72 session
.addAuthorization(this);
75 secdebug("SSauth", "Authorization %p created using %d credentials; owner=%s",
76 this, int(mBaseCreds
.size()),
77 mCreatorCode
? mCreatorCode
->encode().c_str() : "unknown");
80 AuthorizationToken::~AuthorizationToken()
83 assert(mUsingProcesses
.empty());
85 // deregister from parent session
86 if (session
.removeAuthorization(this))
89 secdebug("SSauth", "Authorization %p destroyed", this);
94 // Locate an authorization given its blob.
96 AuthorizationToken
&AuthorizationToken::find(const AuthorizationBlob
&blob
)
98 StLock
<Mutex
> _(authMapLock
);
99 AuthMap::iterator it
= authMap
.find(blob
);
100 if (it
== authMap
.end())
101 Authorization::Error::throwMe(errAuthorizationInvalidRef
);
107 // Handle atomic deletion of AuthorizationToken objects
109 AuthorizationToken::Deleter::Deleter(const AuthorizationBlob
&blob
)
112 AuthMap::iterator it
= authMap
.find(blob
);
113 if (it
== authMap
.end())
114 Authorization::Error::throwMe(errAuthorizationInvalidRef
);
118 void AuthorizationToken::Deleter::remove()
121 authMap
.erase(mAuth
->handle());
129 // Given a set of credentials, add it to our private credentials and return the result
131 // must hold Session::mCredsLock
132 CredentialSet
AuthorizationToken::effectiveCreds() const
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())
145 // Add more credential dependencies to an authorization
147 // must hold Session::mCredsLock
148 void AuthorizationToken::mergeCredentials(const CredentialSet
&add
)
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
);
155 secdebug("SSauth", "Authorization %p merged %d new credentials for %d total",
156 this, int(add
.size()), int(mBaseCreds
.size()));
161 // Register a new process that uses this authorization token.
162 // This is an idempotent operation.
164 void AuthorizationToken::addProcess(Process
&proc
)
166 StLock
<Mutex
> _(mLock
);
167 mUsingProcesses
.insert(&proc
);
168 secdebug("SSauth", "Authorization %p added process %p(%d)", this, &proc
, proc
.pid());
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.
178 bool AuthorizationToken::endProcess(Process
&proc
)
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();
190 // Check whether internalization/externalization is allowed
192 bool AuthorizationToken::mayExternalize(Process
&) const
194 return mTransferCount
> 0;
197 bool AuthorizationToken::mayInternalize(Process
&, bool countIt
)
199 StLock
<Mutex
> _(mLock
);
200 if (mTransferCount
> 0) {
203 secdebug("SSauth", "Authorization %p decrement intcount to %d", this, mTransferCount
);
211 AuthorizationToken::infoSet(AuthorizationString tag
)
213 StLock
<Mutex
> _(mLock
); // consider a separate lock
219 AuthItemSet::iterator found
= find_if(mInfoSet
.begin(), mInfoSet
.end(),
220 Authorization::FindAuthItemByRightName(tag
));
221 if (found
!= mInfoSet
.end())
222 tempSet
.insert(AuthItemRef(*found
));
228 secdebug("SSauth", "Authorization %p returning copy of context %s%s.", this, tag
? "for tag " : "", tag
? "" : tag
);
234 AuthorizationToken::setInfoSet(AuthItemSet
&newInfoSet
)
236 StLock
<Mutex
> _(mLock
); // consider a separate lock
237 secdebug("SSauth", "Authorization %p setting new context", this);
238 mInfoSet
= newInfoSet
;
241 // This is destructive (non-merging)
243 AuthorizationToken::setCredentialInfo(const Credential
&inCred
)
245 AuthItemSet dstInfoSet
;
246 char uid_string
[16]; // fit a uid_t(u_int32_t)
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
);
254 AuthItemRef
userHint("username", AuthValueOverlay(inCred
->username()), 0);
255 dstInfoSet
.insert(userHint
);
257 setInfoSet(dstInfoSet
);