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