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