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