]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/lib/SecAccess.cpp
Security-57740.60.18.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / SecAccess.cpp
1 /*
2 * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <SecBase.h>
25 #include <Security/SecAccess.h>
26 #include <Security/SecAccessPriv.h>
27 #include <Security/SecTrustedApplication.h>
28 #include <Security/SecTrustedApplicationPriv.h>
29 #include <security_keychain/Access.h>
30 #include <security_utilities/casts.h>
31 #include <utilities/SecCFRelease.h>
32 #include "SecBridge.h"
33 #include <sys/param.h>
34
35 #include <utilities/SecCFWrappers.h>
36
37
38 /* No restrictions. Permission to perform all operations on
39 the resource or available to an ACL owner. */
40
41
42 const CFStringRef kSecACLAuthorizationAny = CFSTR("ACLAuthorizationAny");
43
44 const CFStringRef kSecACLAuthorizationLogin = CFSTR("ACLAuthorizationLogin");
45 const CFStringRef kSecACLAuthorizationGenKey = CFSTR("ACLAuthorizationGenKey");
46 const CFStringRef kSecACLAuthorizationDelete = CFSTR("ACLAuthorizationDelete");
47 const CFStringRef kSecACLAuthorizationExportWrapped = CFSTR("ACLAuthorizationExportWrapped");
48 const CFStringRef kSecACLAuthorizationExportClear = CFSTR("ACLAuthorizationExportClear");
49 const CFStringRef kSecACLAuthorizationImportWrapped = CFSTR("ACLAuthorizationImportWrapped");
50 const CFStringRef kSecACLAuthorizationImportClear = CFSTR("ACLAuthorizationImportClear");
51 const CFStringRef kSecACLAuthorizationSign = CFSTR("ACLAuthorizationSign");
52 const CFStringRef kSecACLAuthorizationEncrypt = CFSTR("ACLAuthorizationEncrypt");
53 const CFStringRef kSecACLAuthorizationDecrypt = CFSTR("ACLAuthorizationDecrypt");
54 const CFStringRef kSecACLAuthorizationMAC = CFSTR("ACLAuthorizationMAC");
55 const CFStringRef kSecACLAuthorizationDerive = CFSTR("ACLAuthorizationDerive");
56
57 /* Defined authorization tag values for Keychain */
58
59
60
61 const CFStringRef kSecACLAuthorizationKeychainCreate = CFSTR("ACLAuthorizationKeychainCreate");
62 const CFStringRef kSecACLAuthorizationKeychainDelete = CFSTR("ACLAuthorizationKeychainDelete");
63 const CFStringRef kSecACLAuthorizationKeychainItemRead = CFSTR("ACLAuthorizationKeychainItemRead");
64 const CFStringRef kSecACLAuthorizationKeychainItemInsert = CFSTR("ACLAuthorizationKeychainItemInsert");
65 const CFStringRef kSecACLAuthorizationKeychainItemModify = CFSTR("ACLAuthorizationKeychainItemModify");
66 const CFStringRef kSecACLAuthorizationKeychainItemDelete = CFSTR("ACLAuthorizationKeychainItemDelete");
67
68 const CFStringRef kSecACLAuthorizationChangeACL = CFSTR("ACLAuthorizationChangeACL");
69 const CFStringRef kSecACLAuthorizationChangeOwner = CFSTR("ACLAuthorizationChangeOwner");
70 const CFStringRef kSecACLAuthorizationPartitionID = CFSTR("ACLAuthorizationPartitionID");
71 const CFStringRef kSecACLAuthorizationIntegrity = CFSTR("ACLAuthorizationIntegrity");
72
73
74 static CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trustedAppListFileName);
75
76 static CFStringRef gKeys[] =
77 {
78 kSecACLAuthorizationAny,
79 kSecACLAuthorizationLogin,
80 kSecACLAuthorizationGenKey,
81 kSecACLAuthorizationDelete,
82 kSecACLAuthorizationExportWrapped,
83 kSecACLAuthorizationExportClear,
84 kSecACLAuthorizationImportWrapped,
85 kSecACLAuthorizationImportClear,
86 kSecACLAuthorizationSign,
87 kSecACLAuthorizationEncrypt,
88 kSecACLAuthorizationDecrypt,
89 kSecACLAuthorizationMAC,
90 kSecACLAuthorizationDerive,
91
92 /* Defined authorization tag values for Keychain */
93 kSecACLAuthorizationKeychainCreate,
94 kSecACLAuthorizationKeychainDelete,
95 kSecACLAuthorizationKeychainItemRead,
96 kSecACLAuthorizationKeychainItemInsert,
97 kSecACLAuthorizationKeychainItemModify,
98 kSecACLAuthorizationKeychainItemDelete,
99
100 kSecACLAuthorizationChangeACL,
101 kSecACLAuthorizationChangeOwner,
102 kSecACLAuthorizationPartitionID,
103 kSecACLAuthorizationIntegrity
104 };
105
106 static sint32 gValues[] =
107 {
108 CSSM_ACL_AUTHORIZATION_ANY,
109 CSSM_ACL_AUTHORIZATION_LOGIN,
110 CSSM_ACL_AUTHORIZATION_GENKEY,
111 CSSM_ACL_AUTHORIZATION_DELETE,
112 CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED,
113 CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR,
114 CSSM_ACL_AUTHORIZATION_IMPORT_WRAPPED,
115 CSSM_ACL_AUTHORIZATION_IMPORT_CLEAR,
116 CSSM_ACL_AUTHORIZATION_SIGN,
117 CSSM_ACL_AUTHORIZATION_ENCRYPT,
118 CSSM_ACL_AUTHORIZATION_DECRYPT,
119 CSSM_ACL_AUTHORIZATION_MAC,
120 CSSM_ACL_AUTHORIZATION_DERIVE,
121 CSSM_ACL_AUTHORIZATION_DBS_CREATE,
122 CSSM_ACL_AUTHORIZATION_DBS_DELETE,
123 CSSM_ACL_AUTHORIZATION_DB_READ,
124 CSSM_ACL_AUTHORIZATION_DB_INSERT,
125 CSSM_ACL_AUTHORIZATION_DB_MODIFY,
126 CSSM_ACL_AUTHORIZATION_DB_DELETE,
127 CSSM_ACL_AUTHORIZATION_CHANGE_ACL,
128 CSSM_ACL_AUTHORIZATION_CHANGE_OWNER,
129 CSSM_ACL_AUTHORIZATION_PARTITION_ID,
130 CSSM_ACL_AUTHORIZATION_INTEGRITY
131 };
132
133 static
134 CFDictionaryRef CreateStringToNumDictionary()
135 {
136 int numItems = (sizeof(gValues) / sizeof(sint32));
137 CFMutableDictionaryRef tempDict = CFDictionaryCreateMutable(kCFAllocatorDefault, numItems, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
138
139 for (int iCnt = 0; iCnt < numItems; iCnt++)
140 {
141 sint32 aNumber = gValues[iCnt];
142 CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &aNumber);
143
144 CFStringRef aString = gKeys[iCnt];
145 CFDictionaryAddValue(tempDict, aString, aNum);
146 CFRelease(aNum);
147 }
148
149 CFDictionaryRef result = CFDictionaryCreateCopy(kCFAllocatorDefault, tempDict);
150 CFRelease(tempDict);
151 return result;
152
153 }
154
155 static
156 CFDictionaryRef CreateNumToStringDictionary()
157 {
158 int numItems = (sizeof(gValues) / sizeof(sint32));
159
160 CFMutableDictionaryRef tempDict = CFDictionaryCreateMutable(kCFAllocatorDefault, numItems, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
161
162 for (int iCnt = 0; iCnt < numItems; iCnt++)
163 {
164 sint32 aNumber = gValues[iCnt];
165 CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &aNumber);
166
167 CFStringRef aString = gKeys[iCnt];
168 CFDictionaryAddValue(tempDict, aNum, aString);
169 CFRelease(aNum);
170
171 }
172
173 CFDictionaryRef result = CFDictionaryCreateCopy(kCFAllocatorDefault, tempDict);
174 CFRelease(tempDict);
175 return result;
176 }
177
178
179 /* TODO: This should be in some header */
180 sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr);
181 sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr)
182 {
183 if (NULL == aclStr)
184 {
185 #ifndef NDEBUG
186 CFShow(CFSTR("GetACLAuthorizationTagFromString aclStr is NULL"));
187 #endif
188 return 0;
189 }
190
191 static CFDictionaryRef gACLMapping = NULL;
192
193 if (NULL == gACLMapping)
194 {
195 gACLMapping = CreateStringToNumDictionary();
196 }
197
198 sint32 result = 0;
199 CFNumberRef valueResult = (CFNumberRef)CFDictionaryGetValue(gACLMapping, aclStr);
200 if (NULL != valueResult)
201 {
202 if (!CFNumberGetValue(valueResult, kCFNumberSInt32Type, &result))
203 {
204 return 0;
205 }
206
207 }
208 else
209 {
210 return 0;
211 }
212
213 return result;
214
215 }
216
217 /* TODO: This should be in some header */
218 CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag);
219 CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag)
220 {
221 static CFDictionaryRef gTagMapping = NULL;
222 CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tag);
223
224 if (NULL == gTagMapping)
225 {
226 gTagMapping = CreateNumToStringDictionary();
227 }
228
229 CFStringRef result = (CFStringRef)kSecACLAuthorizationAny;
230
231 if (NULL != gTagMapping && CFDictionaryContainsKey(gTagMapping, aNum))
232 {
233 result = (CFStringRef)CFDictionaryGetValue(gTagMapping, aNum);
234 }
235 CFReleaseSafe(aNum);
236 return result;
237 }
238
239 //
240 // CF boilerplate
241 //
242 CFTypeID SecAccessGetTypeID(void)
243 {
244 BEGIN_SECAPI
245 return gTypes().Access.typeID;
246 END_SECAPI1(_kCFRuntimeNotATypeID)
247 }
248
249
250 //
251 // API bridge calls
252 //
253 /*!
254 * Create a new SecAccessRef that is set to the default configuration
255 * of a (newly created) security object.
256 */
257 OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef trustedList, SecAccessRef *accessRef)
258 {
259 BEGIN_SECAPI
260 Required(descriptor);
261 SecPointer<Access> access;
262 if (trustedList) {
263 CFIndex length = CFArrayGetCount(trustedList);
264 ACL::ApplicationList trusted;
265 for (CFIndex n = 0; n < length; n++)
266 trusted.push_back(TrustedApplication::required(
267 SecTrustedApplicationRef(CFArrayGetValueAtIndex(trustedList, n))));
268 access = new Access(cfString(descriptor), trusted);
269 } else {
270 access = new Access(cfString(descriptor));
271 }
272 Required(accessRef) = access->handle();
273 END_SECAPI
274 }
275
276
277 /*!
278 */
279 OSStatus SecAccessCreateFromOwnerAndACL(const CSSM_ACL_OWNER_PROTOTYPE *owner,
280 uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls,
281 SecAccessRef *accessRef)
282 {
283 BEGIN_SECAPI
284 Required(accessRef); // preflight
285 SecPointer<Access> access = new Access(Required(owner), aclCount, &Required(acls));
286 *accessRef = access->handle();
287 END_SECAPI
288 }
289
290 SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAccessOwnerType ownerType, CFArrayRef acls, CFErrorRef *error)
291 {
292 SecAccessRef result = NULL;
293
294 CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector =
295 {
296 CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, // selector version
297 int_cast<UInt32, uint16>(ownerType),
298 userId,
299 groupId
300 };
301
302 CSSM_LIST_ELEMENT subject2 = { NULL, 0 };
303 subject2.Element.Word.Data = (UInt8 *)&selector;
304 subject2.Element.Word.Length = sizeof(selector);
305 CSSM_LIST_ELEMENT subject1 =
306 {
307 &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID
308 };
309
310 CFIndex numAcls = 0;
311
312 if (NULL != acls)
313 {
314 numAcls = CFArrayGetCount(acls);
315 }
316
317 #ifndef NDEBUG
318 CFStringRef debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
319 CFSTR("SecAccessCreateWithOwnerAndACL: processing %d acls"), (int)numAcls);
320 CFShow(debugStr);
321 CFRelease(debugStr);
322 #endif
323
324 CSSM_ACL_AUTHORIZATION_TAG rights[numAcls];
325 memset(rights, 0, sizeof(rights));
326
327 for (CFIndex iCnt = 0; iCnt < numAcls; iCnt++)
328 {
329 CFStringRef aclStr = (CFStringRef)CFArrayGetValueAtIndex(acls, iCnt);
330
331 #ifndef NDEBUG
332 debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
333 CFSTR("SecAccessCreateWithOwnerAndACL: acls[%d] = %@"), (int)iCnt, aclStr);
334
335 CFShow(debugStr);
336 CFRelease(debugStr);
337 #endif
338
339 CSSM_ACL_AUTHORIZATION_TAG aTag = GetACLAuthorizationTagFromString(aclStr);
340
341 #ifndef NDEBUG
342 debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
343 CFSTR("SecAccessCreateWithOwnerAndACL: rights[%d] = %d"), (int)iCnt, aTag);
344
345 CFShow(debugStr);
346 CFRelease(debugStr);
347 #endif
348
349 rights[iCnt] = aTag;
350 }
351
352
353 for (CFIndex iCnt = 0; iCnt < numAcls; iCnt++)
354 {
355 #ifndef NDEBUG
356 debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
357 CFSTR("SecAccessCreateWithOwnerAndACL: rights[%d] = %d"), (int)iCnt, rights[iCnt]);
358
359 CFShow(debugStr);
360 CFRelease(debugStr);
361 #endif
362
363
364 }
365
366 CSSM_ACL_OWNER_PROTOTYPE owner =
367 {
368 // TypedSubject
369 { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
370 // Delegate
371 false
372 };
373
374
375 // ACL entries (any number, just one here)
376 CSSM_ACL_ENTRY_INFO acl_rights[] =
377 {
378 {
379 // prototype
380 {
381 // TypedSubject
382 { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
383 false, // Delegate
384 // rights for this entry
385 { (uint32)(sizeof(rights) / sizeof(rights[0])), rights },
386 // rest is defaulted
387 }
388 }
389 };
390
391 OSStatus err = SecAccessCreateFromOwnerAndACL(&owner,
392 sizeof(acl_rights) / sizeof(acl_rights[0]), acl_rights, &result);
393
394 if (errSecSuccess != err)
395 {
396 result = NULL;
397 if (NULL != error)
398 {
399 *error = CFErrorCreate(kCFAllocatorDefault, CFSTR("FIX ME"), err, NULL);
400 }
401 }
402 return result;
403 }
404
405
406 /*!
407 */
408 OSStatus SecAccessGetOwnerAndACL(SecAccessRef accessRef,
409 CSSM_ACL_OWNER_PROTOTYPE_PTR *owner,
410 uint32 *aclCount, CSSM_ACL_ENTRY_INFO_PTR *acls)
411 {
412 BEGIN_SECAPI
413 Access::required(accessRef)->copyOwnerAndAcl(
414 Required(owner), Required(aclCount), Required(acls));
415 END_SECAPI
416 }
417
418 OSStatus SecAccessCopyOwnerAndACL(SecAccessRef accessRef, uid_t* userId, gid_t* groupId, SecAccessOwnerType* ownerType, CFArrayRef* aclList)
419 {
420 CSSM_ACL_OWNER_PROTOTYPE_PTR owner = NULL;
421 CSSM_ACL_ENTRY_INFO_PTR acls = NULL;
422 uint32 aclCount = 0;
423 OSStatus result = SecAccessGetOwnerAndACL(accessRef, &owner, &aclCount, &acls);
424 if (errSecSuccess != result )
425 {
426 return result;
427 }
428
429 if (NULL != owner)
430 {
431 CSSM_LIST_ELEMENT_PTR listHead = owner->TypedSubject.Head;
432 if (listHead != NULL && listHead->ElementType == CSSM_LIST_ELEMENT_WORDID)
433 {
434 CSSM_LIST_ELEMENT_PTR nextElement = listHead->NextElement;
435 if (listHead->WordID == CSSM_ACL_SUBJECT_TYPE_PROCESS && listHead->ElementType == CSSM_LIST_ELEMENT_WORDID)
436 {
437 // nextElement contains the required data
438 CSSM_ACL_PROCESS_SUBJECT_SELECTOR* selectorPtr = (CSSM_ACL_PROCESS_SUBJECT_SELECTOR*)nextElement->Element.Word.Data;
439 if (NULL != selectorPtr)
440 {
441 if (NULL != userId)
442 {
443 *userId = (uid_t)selectorPtr->uid;
444 }
445
446 if (NULL != groupId)
447 {
448 *groupId = (gid_t)selectorPtr->gid;
449 }
450
451 if (NULL != ownerType)
452 {
453 *ownerType = (SecAccessOwnerType)selectorPtr->mask;
454 }
455 }
456 }
457
458 }
459
460 }
461
462 if (NULL != aclList)
463 {
464 #ifndef NDEBUG
465 CFShow(CFSTR("SecAccessCopyOwnerAndACL: processing the ACL list"));
466 #endif
467
468 CFMutableArrayRef stringArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
469 CSSM_ACL_OWNER_PROTOTYPE_PTR protoPtr = NULL;
470 uint32 numAcls = 0L;
471 CSSM_ACL_ENTRY_INFO_PTR aclEntry = NULL;
472
473 result = SecAccessGetOwnerAndACL(accessRef, &protoPtr, &numAcls, &aclEntry);
474 if (errSecSuccess == result)
475 {
476 #ifndef NDEBUG
477 CFStringRef tempStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("SecAccessCopyOwnerAndACL: numAcls = %d"), numAcls);
478 CFShow(tempStr);
479 CFRelease(tempStr);
480 #endif
481
482 for (uint32 iCnt = 0; iCnt < numAcls; iCnt++)
483 {
484 CSSM_ACL_ENTRY_PROTOTYPE prototype = aclEntry[iCnt].EntryPublicInfo;
485 CSSM_AUTHORIZATIONGROUP authGroup = prototype.Authorization;
486 int numAuthTags = (int)authGroup.NumberOfAuthTags;
487
488 for (int jCnt = 0; jCnt < numAuthTags; jCnt++)
489 {
490
491 sint32 aTag = authGroup.AuthTags[jCnt];
492 CFStringRef aString = GetAuthStringFromACLAuthorizationTag(aTag);
493
494 CFArrayAppendValue(stringArray, aString);
495 }
496 }
497 }
498
499 if (NULL != stringArray)
500 {
501 if (0 < CFArrayGetCount(stringArray))
502 {
503 *aclList = CFArrayCreateCopy(kCFAllocatorDefault, stringArray);
504 }
505 CFRelease(stringArray);
506 }
507 }
508
509 return result;
510 }
511
512 /*!
513 */
514 OSStatus SecAccessCopyACLList(SecAccessRef accessRef,
515 CFArrayRef *aclList)
516 {
517 BEGIN_SECAPI
518 Required(aclList) = Access::required(accessRef)->copySecACLs();
519 END_SECAPI
520 }
521
522
523 /*!
524 */
525 OSStatus SecAccessCopySelectedACLList(SecAccessRef accessRef,
526 CSSM_ACL_AUTHORIZATION_TAG action,
527 CFArrayRef *aclList)
528 {
529 BEGIN_SECAPI
530 Required(aclList) = Access::required(accessRef)->copySecACLs(action);
531 END_SECAPI
532 }
533
534 CFArrayRef SecAccessCopyMatchingACLList(SecAccessRef accessRef, CFTypeRef authorizationTag)
535 {
536 CFArrayRef result = NULL;
537 CSSM_ACL_AUTHORIZATION_TAG tag = GetACLAuthorizationTagFromString((CFStringRef)authorizationTag);
538 OSStatus err = SecAccessCopySelectedACLList(accessRef, tag, &result);
539 if (errSecSuccess != err)
540 {
541 result = NULL;
542 }
543 return result;
544 }
545
546 CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trustedAppListFileName)
547 {
548 CFStringRef errorString = nil;
549 CFURLRef bundleURL,trustedAppsURL = NULL;
550 CFBundleRef secBundle = NULL;
551 CFPropertyListRef trustedAppsPlist = NULL;
552 CFDataRef xmlDataRef = NULL;
553 SInt32 errorCode;
554 CFArrayRef trustedAppList = NULL;
555 CFMutableStringRef trustedAppListFileNameWithoutExtension = NULL;
556
557 // Make a CFURLRef from the CFString representation of the bundleƕs path.
558 bundleURL = CFURLCreateWithFileSystemPath(
559 kCFAllocatorDefault,bundlePath,kCFURLPOSIXPathStyle,true);
560
561 CFRange wholeStrRange;
562
563 if (!bundleURL)
564 goto xit;
565
566 // Make a bundle instance using the URLRef.
567 secBundle = CFBundleCreate(kCFAllocatorDefault,bundleURL);
568 if (!secBundle)
569 goto xit;
570
571 trustedAppListFileNameWithoutExtension =
572 CFStringCreateMutableCopy(NULL,CFStringGetLength(trustedAppListFileName),trustedAppListFileName);
573 wholeStrRange = CFStringFind(trustedAppListFileName,CFSTR(".plist"),0);
574
575 CFStringDelete(trustedAppListFileNameWithoutExtension,wholeStrRange);
576
577 // Look for a resource in the bundle by name and type
578 trustedAppsURL = CFBundleCopyResourceURL(secBundle,trustedAppListFileNameWithoutExtension,CFSTR("plist"),NULL);
579 if (!trustedAppsURL)
580 goto xit;
581
582 if ( trustedAppListFileNameWithoutExtension )
583 CFRelease(trustedAppListFileNameWithoutExtension);
584
585 if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,trustedAppsURL,&xmlDataRef,NULL,NULL,&errorCode))
586 goto xit;
587
588 trustedAppsPlist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,xmlDataRef,kCFPropertyListImmutable,&errorString);
589 trustedAppList = (CFArrayRef)trustedAppsPlist;
590
591 xit:
592 if (bundleURL)
593 CFRelease(bundleURL);
594 if (secBundle)
595 CFRelease(secBundle);
596 if (trustedAppsURL)
597 CFRelease(trustedAppsURL);
598 if (xmlDataRef)
599 CFRelease(xmlDataRef);
600 if (errorString)
601 CFRelease(errorString);
602
603 return trustedAppList;
604 }
605
606 OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess)
607 {
608 OSStatus err = errSecSuccess;
609 SecAccessRef accessToReturn=nil;
610 CFMutableArrayRef trustedApplications=nil;
611
612 if (!allowAny) // use default access ("confirm access")
613 {
614 // make an exception list of applications you want to trust,
615 // which are allowed to access the item without requiring user confirmation
616 SecTrustedApplicationRef myself=NULL, someOther=NULL;
617 CFArrayRef trustedAppListFromBundle=NULL;
618
619 trustedApplications=CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
620 err = SecTrustedApplicationCreateFromPath(NULL, &myself);
621 if (!err)
622 CFArrayAppendValue(trustedApplications,myself);
623
624 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, trustedApplicationsPListPath, kCFURLPOSIXPathStyle, 0);
625 CFStringRef leafStr = NULL;
626 leafStr = CFURLCopyLastPathComponent(url);
627
628 CFURLRef bndlPathURL = NULL;
629 bndlPathURL = CFURLCreateCopyDeletingLastPathComponent(NULL, url);
630 CFStringRef bndlPath = NULL;
631 bndlPath = CFURLCopyFileSystemPath(bndlPathURL, kCFURLPOSIXPathStyle);
632 trustedAppListFromBundle=copyTrustedAppListFromBundle(bndlPath, leafStr);
633 if ( leafStr )
634 CFRelease(leafStr);
635 if ( bndlPath )
636 CFRelease(bndlPath);
637 if ( url )
638 CFRelease(url);
639 if ( bndlPathURL )
640 CFRelease(bndlPathURL);
641 if (trustedAppListFromBundle)
642 {
643 CFIndex ix,top;
644 char buffer[MAXPATHLEN];
645 top = CFArrayGetCount(trustedAppListFromBundle);
646 for (ix=0;ix<top;ix++)
647 {
648 CFStringRef filename = (CFStringRef)CFArrayGetValueAtIndex(trustedAppListFromBundle,ix);
649 CFIndex stringLength = CFStringGetLength(filename);
650 CFIndex usedBufLen;
651
652 if (stringLength != CFStringGetBytes(filename,CFRangeMake(0,stringLength),kCFStringEncodingUTF8,0,
653 false,(UInt8 *)&buffer,MAXPATHLEN, &usedBufLen))
654 break;
655 buffer[usedBufLen] = 0;
656 //
657 // Support specification of trusted applications by either
658 // a full pathname or a code requirement string.
659 //
660 if (buffer[0]=='/')
661 {
662 err = SecTrustedApplicationCreateFromPath(buffer,&someOther);
663 }
664 else
665 {
666 char *buf = NULL;
667 CFStringRef reqStr = filename;
668 CFArrayRef descArray = CFStringCreateArrayBySeparatingStrings(NULL, reqStr, CFSTR("\""));
669 if (descArray && (CFArrayGetCount(descArray) > 1))
670 {
671 CFStringRef descStr = (CFStringRef) CFArrayGetValueAtIndex(descArray, 1);
672 if (descStr)
673 buf = CFStringToCString(descStr);
674 }
675 SecRequirementRef reqRef = NULL;
676 err = SecRequirementCreateWithString(reqStr, kSecCSDefaultFlags, &reqRef);
677 if (!err)
678 err = SecTrustedApplicationCreateFromRequirement((const char *)buf, reqRef, &someOther);
679 if (buf)
680 free(buf);
681 CFReleaseSafe(reqRef);
682 CFReleaseSafe(descArray);
683 }
684 if (!err)
685 CFArrayAppendValue(trustedApplications,someOther);
686
687 if (someOther)
688 CFReleaseNull(someOther);
689 }
690 CFRelease(trustedAppListFromBundle);
691 }
692 }
693
694 err = SecAccessCreate((CFStringRef)accessLabel, (CFArrayRef)trustedApplications, &accessToReturn);
695 if (!err)
696 {
697 if (allowAny) // change access to be wide-open for decryption ("always allow access")
698 {
699 // get the access control list for decryption operations
700 CFArrayRef aclList=nil;
701 err = SecAccessCopySelectedACLList(accessToReturn, CSSM_ACL_AUTHORIZATION_DECRYPT, &aclList);
702 if (!err)
703 {
704 // get the first entry in the access control list
705 SecACLRef aclRef=(SecACLRef)CFArrayGetValueAtIndex(aclList, 0);
706 CFArrayRef appList=nil;
707 CFStringRef promptDescription=nil;
708 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector;
709 err = SecACLCopySimpleContents(aclRef, &appList, &promptDescription, &promptSelector);
710
711 // modify the default ACL to not require the passphrase, and have a nil application list
712 promptSelector.flags &= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE;
713 err = SecACLSetSimpleContents(aclRef, NULL, promptDescription, &promptSelector);
714
715 if (appList) CFRelease(appList);
716 if (promptDescription) CFRelease(promptDescription);
717 }
718 }
719 }
720 *returnedAccess = accessToReturn;
721 return err;
722 }