1/* 2 * Copyright (c) 2003-2013 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 * SecKeychainAddIToolsPassword.c 24 * 25 * Based on Keychain item access control example 26 * -- added "always allow" ACL support 27 */ 28 29#include <Security/SecKeychain.h> 30#include <Security/SecKeychainItem.h> 31#include <Security/SecAccess.h> 32#include <Security/SecAccessPriv.h> 33#include <Security/SecTrustedApplicationPriv.h> 34#include <Security/SecACL.h> 35#include "SecBridge.h" 36#include <CoreFoundation/CoreFoundation.h> 37#include <security_utilities/cfutilities.h> 38 39 40OSStatus SecKeychainAddIToolsPassword(SecKeychainRef keychain, UInt32 accountNameLength, const char *accountName, 41 UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef) 42{ 43 BEGIN_SECAPI 44 45 const char *serviceUTF8 = "iTools"; 46 47 // create the initial ACL label string (use the account name, not "iTools") 48 CFRef<CFStringRef> itemLabel = CFStringCreateWithBytes(kCFAllocatorDefault, 49 (const UInt8 *)accountName, accountNameLength, kCFStringEncodingUTF8, FALSE); 50 51 // accumulate applications in this list 52 CFRef<CFMutableArrayRef> apps = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 53 54 // add entries for application groups 55 CFRef<SecTrustedApplicationRef> dotMacGroup, accountsGroup; 56 MacOSError::check(SecTrustedApplicationCreateApplicationGroup("dot-mac", NULL, &dotMacGroup.aref())); 57 CFArrayAppendValue(apps, dotMacGroup); 58 MacOSError::check(SecTrustedApplicationCreateApplicationGroup("InternetAccounts", NULL, &accountsGroup.aref())); 59 CFArrayAppendValue(apps, accountsGroup); 60 61 // now add "myself" as an ordinary application 62 CFRef<SecTrustedApplicationRef> myself; 63 MacOSError::check(SecTrustedApplicationCreateFromPath(NULL, &myself.aref())); 64 CFArrayAppendValue(apps, myself); 65 66 // now add the pre-cooked list of .Mac applications for systems that don't understand the group semantics 67 if (CFRef<CFBundleRef> myBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security"))) 68 if (CFRef<CFURLRef> url = CFBundleCopyResourceURL(myBundle, 69 CFSTR("iToolsTrustedApps"), CFSTR("plist"), NULL)) { 70 CFRef<CFDataRef> data; 71 if (CFURLCreateDataAndPropertiesFromResource(NULL, url, &data.aref(), NULL, NULL, NULL)) 72 if (CFRef<CFArrayRef> list = 73 CFArrayRef(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL))) { 74 CFIndex size = CFArrayGetCount(list); 75 for (CFIndex n = 0; n < size; n++) { 76 CFStringRef path = (CFStringRef)CFArrayGetValueAtIndex(list, n); 77 CFRef<SecTrustedApplicationRef> app; 78 if (SecTrustedApplicationCreateFromPath(cfString(path).c_str(), &app.aref()) == errSecSuccess) 79 CFArrayAppendValue(apps, app); 80 } 81 } 82 } 83 84 // form a SecAccess from this 85 CFRef<SecAccessRef> access; 86 MacOSError::check(SecAccessCreate(itemLabel, (CFArrayRef)apps, &access.aref())); 87 88 // set up attribute vector (each attribute consists of {tag, length, pointer}) 89 SecKeychainAttribute attrs[] = { 90 { kSecLabelItemAttr, accountNameLength, (char *)accountName }, // use the account name as the label for display purposes [3787371] 91 { kSecAccountItemAttr, accountNameLength, (char *)accountName }, 92 { kSecServiceItemAttr, (UInt32)strlen(serviceUTF8), (char *)serviceUTF8 } 93 }; 94 SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs }; 95 96 return SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, 97 &attributes, 98 passwordLength, 99 (const char *)passwordData, 100 keychain, 101 access, 102 itemRef); 103 104 END_SECAPI 105} 106