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