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