]> git.saurik.com Git - apple/security.git/blob - Keychain/Access.cpp
Security-54.1.3.tar.gz
[apple/security.git] / Keychain / Access.cpp
1 /*
2 * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18 //
19 // Access.cpp
20 //
21 #include <Security/Access.h>
22 #include <Security/SecBase.h>
23 #include "SecBridge.h"
24 #include <Security/devrandom.h>
25 #include <Security/uniformrandom.h>
26 #include <vector>
27
28 using namespace KeychainCore;
29
30
31 //
32 // Create a completely open Access (anyone can do anything)
33 // Note that this means anyone can *change* the ACL at will, too.
34 // These ACL entries contain no descriptor names.
35 //
36 Access::Access()
37 {
38 RefPointer<ACL> owner = new ACL(*this);
39 owner->setAuthorization(CSSM_ACL_AUTHORIZATION_CHANGE_ACL);
40 addOwner(owner);
41
42 RefPointer<ACL> any = new ACL(*this);
43 add(any);
44 }
45
46
47 //
48 // Create a default Access object.
49 // This construct an Access with "default form", whatever that happens to be
50 // in this release.
51 //
52 Access::Access(const string &descriptor, const ACL::ApplicationList &trusted)
53 {
54 makeStandard(descriptor, trusted);
55 }
56
57 Access::Access(const string &descriptor)
58 {
59 ACL::ApplicationList trusted;
60 trusted.push_back(new TrustedApplication);
61 makeStandard(descriptor, trusted);
62 }
63
64 Access::Access(const string &descriptor, const ACL::ApplicationList &trusted,
65 const AclAuthorizationSet &limitedRights, const AclAuthorizationSet &freeRights)
66 {
67 makeStandard(descriptor, trusted, limitedRights, freeRights);
68 }
69
70 void Access::makeStandard(const string &descriptor, const ACL::ApplicationList &trusted,
71 const AclAuthorizationSet &limitedRights, const AclAuthorizationSet &freeRights)
72 {
73 // owner "entry"
74 RefPointer<ACL> owner = new ACL(*this, descriptor, ACL::defaultSelector);
75 owner->setAuthorization(CSSM_ACL_AUTHORIZATION_CHANGE_ACL);
76 addOwner(owner);
77
78 // unlimited entry
79 RefPointer<ACL> unlimited = new ACL(*this, descriptor, ACL::defaultSelector);
80 if (freeRights.empty()) {
81 unlimited->authorizations().clear();
82 unlimited->authorizations().insert(CSSM_ACL_AUTHORIZATION_ENCRYPT);
83 } else
84 unlimited->authorizations() = freeRights;
85 unlimited->form(ACL::allowAllForm);
86 add(unlimited);
87
88 // limited entry
89 RefPointer<ACL> limited = new ACL(*this, descriptor, ACL::defaultSelector);
90 if (limitedRights.empty()) {
91 limited->authorizations().clear();
92 limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_DECRYPT);
93 limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_SIGN);
94 limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_MAC);
95 limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_DERIVE);
96 limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR);
97 limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED);
98 } else
99 limited->authorizations() = limitedRights;
100 limited->applications() = trusted;
101 add(limited);
102 }
103
104
105 //
106 // Create an Access object whose initial value is taken
107 // from a CSSM ACL bearing object.
108 //
109 Access::Access(AclBearer &source)
110 {
111 // retrieve and set
112 AutoAclOwnerPrototype owner;
113 source.getOwner(owner);
114 AutoAclEntryInfoList acls;
115 source.getAcl(acls);
116 compile(*owner, acls.count(), acls.entries());
117 }
118
119
120 //
121 // Create an Access object from CSSM-layer access controls
122 //
123 Access::Access(const CSSM_ACL_OWNER_PROTOTYPE &owner,
124 uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls)
125 {
126 compile(owner, aclCount, acls);
127 }
128
129
130 Access::~Access()
131 {
132 }
133
134
135 //
136 // Return all ACL components in a newly-made CFArray.
137 //
138 CFArrayRef Access::copySecACLs() const
139 {
140 return makeCFArray(gTypes().acl, mAcls);
141 }
142
143 CFArrayRef Access::copySecACLs(CSSM_ACL_AUTHORIZATION_TAG action) const
144 {
145 list<ACL *> choices;
146 for (Map::const_iterator it = mAcls.begin(); it != mAcls.end(); it++)
147 if (it->second->authorizes(action))
148 choices.push_back(it->second);
149 return choices.empty() ? NULL : makeCFArray(gTypes().acl, choices);
150 }
151
152
153 //
154 // Enter the complete access configuration into a AclBearer.
155 // If update, skip any part marked unchanged. (If not update, skip
156 // any part marked deleted.)
157 //
158 void Access::setAccess(AclBearer &target, bool update /* = false */)
159 {
160 AclFactory factory;
161 editAccess(target, update, factory.promptCred());
162 }
163
164 void Access::setAccess(AclBearer &target, Maker &maker)
165 {
166 // remove initial-setup ACL
167 target.deleteAcl(Maker::creationEntryTag, maker.cred());
168
169 // insert our own ACL entries
170 editAccess(target, false, maker.cred());
171 }
172
173 void Access::editAccess(AclBearer &target, bool update, const AccessCredentials *cred)
174 {
175 assert(mAcls[ownerHandle]); // have owner
176
177 // apply all non-owner ACLs first
178 for (Map::iterator it = mAcls.begin(); it != mAcls.end(); it++)
179 if (!it->second->isOwner())
180 it->second->setAccess(target, update, cred);
181
182 // finally, apply owner
183 mAcls[ownerHandle]->setAccess(target, update, cred);
184 }
185
186
187 //
188 // A convenience function to add one application to a standard ("simple") form
189 // ACL entry. This will only work if
190 // -- there is exactly one ACL entry authorizing the right
191 // -- that entry is in simple form
192 //
193 void Access::addApplicationToRight(AclAuthorization right, TrustedApplication *app)
194 {
195 vector<ACL *> acls;
196 findAclsForRight(right, acls);
197 if (acls.size() != 1)
198 MacOSError::throwMe(errSecACLNotSimple); // let's not guess here...
199 (*acls.begin())->addApplication(app);
200 }
201
202
203 //
204 // Retrieve the description from a randomly chosen ACL within this Access.
205 // In the conventional case where all ACLs have the same descriptor, this
206 // is deterministic. But you have been warned.
207 //
208 string Access::promptDescription() const
209 {
210 for (Map::const_iterator it = mAcls.begin(); it != mAcls.end(); it++) {
211 ACL *acl = it->second;
212 switch (acl->form()) {
213 case ACL::allowAllForm:
214 case ACL::appListForm:
215 {
216 string descr = acl->promptDescription();
217 if (!descr.empty())
218 return descr;
219 }
220 default:
221 break;
222 }
223 }
224 // couldn't find suitable ACL (no description anywhere)
225 CssmError::throwMe(errSecACLNotSimple);
226 }
227
228
229 //
230 // Add a new ACL to the resident set. The ACL must have been
231 // newly made for this Access.
232 //
233 void Access::add(ACL *newAcl)
234 {
235 if (&newAcl->access != this)
236 MacOSError::throwMe(paramErr);
237 assert(!mAcls[newAcl->entryHandle()]);
238 mAcls[newAcl->entryHandle()] = newAcl;
239 }
240
241
242 //
243 // Add the owner ACL to the resident set. The ACL must have been
244 // newly made for this Access.
245 // Since an Access must have exactly one owner ACL, this call
246 // should only be made (exactly once) for a newly created Access.
247 //
248 void Access::addOwner(ACL *newAcl)
249 {
250 newAcl->makeOwner();
251 assert(mAcls.find(ownerHandle) == mAcls.end()); // no owner yet
252 add(newAcl);
253 }
254
255
256 //
257 // Compile a set of ACL entries and owner into internal form.
258 //
259 void Access::compile(const CSSM_ACL_OWNER_PROTOTYPE &owner,
260 uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls)
261 {
262 // add owner acl
263 mAcls[ownerHandle] = new ACL(*this, AclOwnerPrototype::overlay(owner));
264
265 // add acl entries
266 const AclEntryInfo *acl = AclEntryInfo::overlay(acls);
267 for (uint32 n = 0; n < aclCount; n++) {
268 debug("SecAccess", "%p compiling entry %ld", this, acl[n].handle());
269 mAcls[acl[n].handle()] = new ACL(*this, acl[n]);
270 }
271 debug("SecAccess", "%p %ld entries compiled", this, mAcls.size());
272 }
273
274
275 //
276 // Creation helper objects
277 //
278 const char Access::Maker::creationEntryTag[] = "___setup___";
279
280 Access::Maker::Maker(CssmAllocator &alloc)
281 : allocator(alloc), mKey(alloc), mCreds(allocator)
282 {
283 // generate random key
284 mKey.malloc(keySize);
285 UniformRandomBlobs<DevRandomGenerator>().random(mKey.get());
286
287 // create entry info for resource creation
288 mInput = AclEntryPrototype(TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_PASSWORD,
289 new(allocator) ListElement(mKey.get())));
290 mInput.proto().tag(creationEntryTag);
291
292 // create credential sample for access
293 mCreds += TypedList(allocator, CSSM_SAMPLE_TYPE_PASSWORD, new(allocator) ListElement(mKey.get()));
294 }
295
296 void Access::Maker::initialOwner(ResourceControlContext &ctx, const AccessCredentials *creds)
297 {
298 //@@@ make up ctx.entry-info
299 ctx.input() = mInput;
300 ctx.credentials(creds);
301 }
302
303 const AccessCredentials *Access::Maker::cred()
304 {
305 return &mCreds;
306 }