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