]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_client/aclsupport.cpp
Security-54.tar.gz
[apple/security.git] / cdsa / cdsa_client / aclsupport.cpp
1 /*
2 * Copyright (c) 2000-2001 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 //
20 // aclsupport.h - support for special Keychain style acls
21 //
22
23 #include <Security/osxsigning.h>
24 #include <Security/osxsigner.h>
25 #include <Security/trackingallocator.h>
26 #include "aclsupport.h"
27 #include "keychainacl.h"
28 #include <memory>
29
30 using namespace CssmClient;
31
32
33 // ---------------------------------------------------------------------------
34 // TrustedApplicationImpl
35 // ---------------------------------------------------------------------------
36
37 TrustedApplicationImpl::TrustedApplicationImpl(const CssmData &signature, const CssmData &comment, bool enabled) :
38 mSignature(CssmAllocator::standard(), signature),
39 mComment(CssmAllocator::standard(), comment),
40 mEnabled(enabled)
41 {
42 }
43
44 TrustedApplicationImpl::TrustedApplicationImpl(const char *path, const CssmData &comment, bool enabled) : mSignature(CssmAllocator::standard()),
45 mComment(CssmAllocator::standard(), comment),
46 mEnabled(enabled)
47 {
48 calcSignature(path, mSignature);
49 }
50
51
52 const CssmData & TrustedApplicationImpl::signature() const
53 {
54
55 return mSignature;
56 }
57
58 const CssmData & TrustedApplicationImpl::comment() const
59 {
60 return mComment;
61 }
62
63 bool TrustedApplicationImpl::enabled() const
64 {
65 return mEnabled;
66 }
67
68 void TrustedApplicationImpl::enabled(bool enabled)
69 {
70 mEnabled = enabled;
71 }
72
73 bool TrustedApplicationImpl::sameSignature(const char *path)
74 {
75 // return true if object at given path has same signature
76 CssmAutoData otherSignature(CssmAllocator::standard());
77 calcSignature(path, otherSignature);
78 return (mSignature.get() == otherSignature);
79 }
80
81 void TrustedApplicationImpl::calcSignature(const char *path, CssmOwnedData &signature)
82 {
83 // generate a signature for the given object
84 RefPointer<CodeSigning::OSXCode> objToVerify(CodeSigning::OSXCode::at(path));
85 CodeSigning::OSXSigner signer;
86 auto_ptr<CodeSigning::OSXSigner::OSXSignature> osxSignature(signer.sign(*objToVerify));
87 signature.copy(osxSignature->data(), osxSignature->length());
88 }
89
90 // ---------------------------------------------------------------------------
91 // TrustedApplication
92 // ---------------------------------------------------------------------------
93
94 TrustedApplication::TrustedApplication()
95 {
96 }
97
98 TrustedApplication::TrustedApplication(
99 const char *path, const CssmData &comment, bool enabled) :
100 RefPointer<TrustedApplicationImpl>(new TrustedApplicationImpl(path, comment, enabled))
101 {
102 }
103
104 TrustedApplication::TrustedApplication(
105 const CssmData &signature, const CssmData &comment, bool enabled) :
106 RefPointer<TrustedApplicationImpl>(new TrustedApplicationImpl(signature, comment, enabled))
107 {
108 }
109
110 // ---------------------------------------------------------------------------
111 // KeychainACL
112 // ---------------------------------------------------------------------------
113
114 KeychainACL::KeychainACL(const Key &key) :
115 mLabel(CssmAllocator::standard()), mSelector(CssmAllocator::standard())
116 {
117 mKey = key;
118 initialize();
119 }
120
121 void KeychainACL::initialize()
122 {
123 mAnyAllow=false;
124 mAlwaysAskUser=false;
125
126 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR defaultSelector
127 = { CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION, 0 };
128 mSelector.copy(&defaultSelector, sizeof(defaultSelector));
129
130 AutoAclEntryInfoList aclInfos;
131 mKey->getAcl(aclInfos);
132 mHandle = CSSM_INVALID_HANDLE;
133 const AclEntryInfo *theInfo = NULL;
134 for(uint32 entry=0; entry<aclInfos.size(); entry++)
135 {
136 const AclEntryInfo &info = aclInfos[entry];
137 const AuthorizationGroup &authorizationGroup=info.proto().authorization();
138 for(uint32 auth=0; auth<authorizationGroup.count(); auth++)
139 {
140 if(authorizationGroup[auth]==CSSM_ACL_AUTHORIZATION_DECRYPT || authorizationGroup[auth]==CSSM_ACL_AUTHORIZATION_ANY)
141 {
142 if (mHandle != CSSM_INVALID_HANDLE && mHandle != info.handle())
143 {
144 mIsCustomACL=true;
145 return;
146 }
147
148 mHandle = info.handle();
149 theInfo = &info;
150 }
151 }
152 }
153 if (!theInfo)
154 {
155 mIsCustomACL=true;
156 return;
157 }
158
159 TypedList subject=theInfo->proto().subject();
160 assert(subject.isProper());
161 const ListElement *element = subject.first();
162
163 switch(*element)
164 {
165 case CSSM_ACL_SUBJECT_TYPE_ANY:
166 assert(element->next() == NULL);
167 mAnyAllow=true;
168 return;
169
170 case CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT:
171 mAlwaysAskUser=true;
172 assert(subject.length() == 3);
173 mSelector = subject[1].data();
174 mLabel = subject[2].data();
175 return;
176
177 case CSSM_ACL_SUBJECT_TYPE_THRESHOLD:
178 break;
179
180 default:
181 mIsCustomACL = true;
182 return;
183 }
184
185 // OK, it's a threshold acl
186 element = element->next();
187 assert(element && element->type() == CSSM_LIST_ELEMENT_WORDID);
188 if (*element != 1) {
189 mIsCustomACL = true;
190 return;
191 }
192 element = element->next();
193 assert(element && element->type() == CSSM_LIST_ELEMENT_WORDID);
194 uint32 n = *element;
195 assert(n > 0);
196
197 int isEnabled=1;
198 for (uint32 ix = 0; ix < n; ++ix)
199 {
200 element = element->next();
201 assert(element && element->type() == CSSM_LIST_ELEMENT_SUBLIST);
202 const TypedList &subList = *element;
203 assert(subList.isProper());
204 const ListElement *subElement = subList.first();
205
206 switch(*subElement)
207 {
208 case CSSM_ACL_SUBJECT_TYPE_ANY:
209 // Must be first subList in list.
210 assert(ix == 0 && subElement->next() == NULL);
211 mAnyAllow=true;
212 break;
213
214 case CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT:
215 // Must be last subList in list.
216 assert(ix == n - 1);
217 mAlwaysAskUser=true;
218 assert(subList.length() == 3);
219 mSelector = subList[1].data();
220 mLabel = subList[2].data();
221 break;
222
223
224 case CSSM_ACL_SUBJECT_TYPE_COMMENT:
225 case CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE:
226 {
227 // when the app is disabled it is commented out.
228 if(*subElement==CSSM_ACL_SUBJECT_TYPE_COMMENT)
229 {
230 isEnabled=0;
231 subElement = subElement->next();
232 }
233 subElement = subElement->next();
234 assert(subElement && subElement->type() == CSSM_LIST_ELEMENT_WORDID);
235 uint32 sigType = *subElement;
236 subElement = subElement->next();
237 assert(subElement && subElement->type() == CSSM_LIST_ELEMENT_DATUM);
238 const CssmData &sig = subElement->data();
239 subElement = subElement->next();
240 assert(subElement && subElement->type() == CSSM_LIST_ELEMENT_DATUM && subElement->next() == NULL);
241 const CssmData &comment = subElement->data();
242 // Only if sigType is CSSM_ACL_CODE_SIGNATURE_OSX this element is enabled.
243 // @@@ Otherwsie it should be CSSM_ACL_CODE_SIGNATURE_NONE (which is not defined yet).
244 // additionally the enabled flag must be respected.
245 push_back(TrustedApplication(sig, comment, (sigType == CSSM_ACL_CODE_SIGNATURE_OSX) && isEnabled));
246 break;
247 }
248
249 default:
250 mIsCustomACL = true;
251 return;
252 }
253 }
254
255 // Since we looked at N values we should be done.
256 assert(element->next() == NULL);
257 }
258
259 void KeychainACL::commit()
260 {
261 TrackingAllocator allocator(CssmAllocator::standard());
262
263 // hhs replaced with new aclFactory
264 AclFactory aclFactory;
265
266 CssmList &list = *new(allocator) CssmList();
267
268 list.append(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_THRESHOLD));
269 list.append(new(allocator) ListElement(1));
270 list.append(new(allocator) ListElement(size()+mAnyAllow+mAlwaysAskUser));
271
272 if(mAnyAllow)
273 {
274 CssmList &sublist = *new(allocator) CssmList();
275 sublist.append(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_ANY));
276 list.append(new(allocator) ListElement(sublist));
277 }
278
279
280 for (uint32 ix = 0; ix < size(); ++ix)
281 {
282 TrustedApplication app = at(ix);
283 CssmList &sublist = *new(allocator) CssmList();
284 if(!app->enabled()) sublist.append(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_COMMENT));
285 sublist.append(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE));
286 sublist.append(new(allocator) ListElement(CSSM_ACL_CODE_SIGNATURE_OSX));
287 sublist.append(new(allocator) ListElement(app->signature()));
288 sublist.append(new(allocator) ListElement(app->comment()));
289 list.append(new(allocator) ListElement(sublist));
290 }
291
292 if(mAlwaysAskUser)
293 {
294 CssmList &sublist = *new(allocator) CssmList();
295 sublist.append(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT));
296 sublist.append(new(allocator) ListElement(mSelector.get()));
297 sublist.append(new(allocator) ListElement(mLabel.get()));
298 list.append(new(allocator) ListElement(sublist));
299 }
300
301 AclEntryPrototype aclEntry(list);
302 // @@@ @@@ Force "decrypt" authorization for now -- should take this from input!! @@@
303 AuthorizationGroup &anyDecryptAuthGroup = aclEntry.authorization();
304 CSSM_ACL_AUTHORIZATION_TAG decryptTag = CSSM_ACL_AUTHORIZATION_DECRYPT;
305 anyDecryptAuthGroup.NumberOfAuthTags = 1;
306 anyDecryptAuthGroup.AuthTags = &decryptTag;
307 const AccessCredentials *promptCred = aclFactory.promptCred ();
308 AclEdit edit(mHandle, aclEntry);
309 mKey->changeAcl(edit, promptCred);
310 }
311
312 void KeychainACL::anyAllow(bool allow)
313 {
314 mAnyAllow=allow;
315 }
316
317 bool KeychainACL::anyAllow() const
318 {
319 return mAnyAllow;
320 }
321
322 void KeychainACL::alwaysAskUser(bool ask)
323 {
324 mAlwaysAskUser=ask;
325 }
326
327 bool KeychainACL::alwaysAskUser() const
328 {
329 return mAlwaysAskUser;
330 }
331
332 bool KeychainACL::isCustomACL() const
333 {
334 return mIsCustomACL;
335 }
336
337 void KeychainACL::label(const CssmData &label)
338 {
339 mLabel = label;
340 }