1/* 2 * Copyright (c) 2013-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 25// 26// si-72-syncableitems.c 27// regressions 28// 29// 30// 31#include <CoreFoundation/CoreFoundation.h> 32#include <Security/Security.h> 33#include <Security/SecItemPriv.h> 34#include <Security/SecInternal.h> 35#include <utilities/array_size.h> 36 37#include "Security_regressions.h" 38 39static void tests(void) 40{ 41 CFUUIDRef uuid = CFUUIDCreate(0); 42 const CFStringRef uuidstr = CFUUIDCreateString(0, uuid); 43 const CFStringRef account = CFStringCreateWithFormat(NULL, NULL, CFSTR("Test Account %@"), uuidstr); 44 const CFStringRef service = CFSTR("Test Service"); 45 const CFStringRef label = CFSTR("Test Synchronizable Item"); 46 const CFStringRef comment = CFSTR("Test Comment"); 47 const CFDataRef passwordData = CFDataCreate(NULL, (const UInt8*)"Test", (CFIndex)5); 48 49 CFReleaseSafe(uuid); 50 CFReleaseSafe(uuidstr); 51 52 CFDictionaryRef query = NULL; 53 CFDictionaryRef attrs = NULL; 54 CFDictionaryRef result = NULL; 55 56 /* Test adding a synchronizable item */ 57 { 58 const void *keys[] = { 59 kSecClass, kSecAttrLabel, kSecAttrComment, kSecAttrAccount, kSecAttrService, 60 kSecAttrSynchronizable, 61 kSecValueData, kSecReturnAttributes }; 62 const void *values[] = { 63 kSecClassGenericPassword, label, comment, account, service, 64 kCFBooleanTrue, 65 passwordData, kCFBooleanTrue }; 66 67 attrs = CFDictionaryCreate(NULL, keys, values, 68 array_size(keys), 69 &kCFTypeDictionaryKeyCallBacks, 70 &kCFTypeDictionaryValueCallBacks); 71 72 is_status(SecItemAdd(attrs, (CFTypeRef *)&result), 73 errSecSuccess, "SecItemAdd sync=true"); 74 75 CFReleaseSafe(attrs); 76 CFReleaseNull(result); 77 } 78 79 /* Test finding the synchronizable item we just added, using sync=true */ 80 { 81 const void *keys[] = { 82 kSecClass, // class attribute is required 83 kSecAttrAccount, kSecAttrService, // we'll look up by account and service, which determine uniqueness 84 kSecAttrSynchronizable, // we want to get synchronizable results 85 kSecReturnAttributes }; 86 const void *values[] = { 87 kSecClassGenericPassword, 88 account, service, 89 kCFBooleanTrue, // only return synchronizable results 90 kCFBooleanTrue }; 91 92 query = CFDictionaryCreate(NULL, keys, values, 93 array_size(keys), 94 &kCFTypeDictionaryKeyCallBacks, 95 &kCFTypeDictionaryValueCallBacks); 96 97 is_status(SecItemCopyMatching(query, (CFTypeRef *)&result), 98 errSecSuccess, "SecItemCopyMatching sync=true"); 99 100 CFReleaseSafe(query); 101 CFReleaseNull(result); 102 } 103 104 /* Test finding the synchronizable item we just added, using sync=any */ 105 { 106 const void *keys[] = { 107 kSecClass, // class attribute is required 108 kSecAttrAccount, kSecAttrService, // we'll look up by account and service, which determine uniqueness 109 kSecAttrSynchronizable, // we want to get synchronizable results 110 kSecReturnAttributes }; 111 const void *values[] = { 112 kSecClassGenericPassword, 113 account, service, 114 kSecAttrSynchronizableAny, // return any match, regardless of whether it is synchronizable 115 kCFBooleanTrue }; 116 117 query = CFDictionaryCreate(NULL, keys, values, 118 array_size(keys), 119 &kCFTypeDictionaryKeyCallBacks, 120 &kCFTypeDictionaryValueCallBacks); 121 122 is_status(SecItemCopyMatching(query, (CFTypeRef *)&result), 123 errSecSuccess, "SecItemCopyMatching sync=any"); 124 125 CFReleaseSafe(query); 126 CFReleaseNull(result); 127 } 128 129 /* Test updating the synchronizable item */ 130 { 131 const void *keys[] = { 132 kSecClass, // class attribute is required 133 kSecAttrAccount, kSecAttrService, // we'll look up by account and service, which determine uniqueness 134 kSecAttrSynchronizable }; // we want synchronizable results 135 const void *values[] = { 136 kSecClassGenericPassword, 137 account, service, 138 kCFBooleanTrue }; // we only want to find the synchronizable item here, not a non-synchronizable one 139 140 query = CFDictionaryCreate(NULL, keys, values, 141 array_size(keys), 142 &kCFTypeDictionaryKeyCallBacks, 143 &kCFTypeDictionaryValueCallBacks); 144 145 const void *update_keys[] = { kSecAttrComment }; 146 const void *update_values[] = { CFSTR("Updated Comment") }; 147 attrs = CFDictionaryCreate(NULL, update_keys, update_values, 148 array_size(update_keys), 149 &kCFTypeDictionaryKeyCallBacks, 150 &kCFTypeDictionaryValueCallBacks); 151 152 is_status(SecItemUpdate(query, attrs), 153 errSecSuccess, "SecItemUpdate sync=true"); 154 155 CFReleaseSafe(query); 156 CFReleaseSafe(attrs); 157 } 158 159 /* Test finding the updated item with its new attribute */ 160 { 161 const void *keys[] = { 162 kSecClass, // class attribute is required 163 kSecAttrAccount, kSecAttrService, // we'll look up by account and service, which determine uniqueness 164 kSecAttrComment, // also search on the attr we just changed, so we know we've found the updated item 165 kSecAttrSynchronizable }; // we want synchronizable results 166 const void *values[] = { 167 kSecClassGenericPassword, 168 account, service, 169 CFSTR("Updated Comment"), 170 kCFBooleanTrue }; // we only want to find the synchronizable item here, not a non-synchronizable one 171 172 query = CFDictionaryCreate(NULL, keys, values, 173 array_size(keys), 174 &kCFTypeDictionaryKeyCallBacks, 175 &kCFTypeDictionaryValueCallBacks); 176 177 is_status(SecItemCopyMatching(query, (CFTypeRef *)&result), 178 errSecSuccess, "SecItemCopyMatching post-update"); 179 180 CFReleaseSafe(result); 181 // re-use query in next test... 182 } 183 184 /* Test deleting the item */ 185 { 186 is_status(SecItemDelete(query), errSecSuccess, "SecItemDelete sync=true"); 187 188 CFReleaseSafe(query); 189 } 190} 191 192int si_72_syncableitems(int argc, char * const *argv) 193{ 194 plan_tests(6); 195 tests(); 196 197 return 0; 198} 199