2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // si-72-syncableitems.c
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>
37 #include "Security_regressions.h"
39 static void tests(void)
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);
50 CFReleaseSafe(uuidstr
);
52 CFDictionaryRef query
= NULL
;
53 CFDictionaryRef attrs
= NULL
;
54 CFDictionaryRef result
= NULL
;
56 /* Test adding a synchronizable item */
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
,
65 passwordData
, kCFBooleanTrue
};
67 attrs
= CFDictionaryCreate(NULL
, keys
, values
,
69 &kCFTypeDictionaryKeyCallBacks
,
70 &kCFTypeDictionaryValueCallBacks
);
72 is_status(SecItemAdd(attrs
, (CFTypeRef
*)&result
),
73 errSecSuccess
, "SecItemAdd sync=true");
76 CFReleaseNull(result
);
79 /* Test finding the synchronizable item we just added, using sync=true */
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
,
89 kCFBooleanTrue
, // only return synchronizable results
92 query
= CFDictionaryCreate(NULL
, keys
, values
,
94 &kCFTypeDictionaryKeyCallBacks
,
95 &kCFTypeDictionaryValueCallBacks
);
97 is_status(SecItemCopyMatching(query
, (CFTypeRef
*)&result
),
98 errSecSuccess
, "SecItemCopyMatching sync=true");
100 CFReleaseSafe(query
);
101 CFReleaseNull(result
);
104 /* Test finding the synchronizable item we just added, using sync=any */
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
,
114 kSecAttrSynchronizableAny
, // return any match, regardless of whether it is synchronizable
117 query
= CFDictionaryCreate(NULL
, keys
, values
,
119 &kCFTypeDictionaryKeyCallBacks
,
120 &kCFTypeDictionaryValueCallBacks
);
122 is_status(SecItemCopyMatching(query
, (CFTypeRef
*)&result
),
123 errSecSuccess
, "SecItemCopyMatching sync=any");
125 CFReleaseSafe(query
);
126 CFReleaseNull(result
);
129 /* Test updating the synchronizable item */
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
,
138 kCFBooleanTrue
}; // we only want to find the synchronizable item here, not a non-synchronizable one
140 query
= CFDictionaryCreate(NULL
, keys
, values
,
142 &kCFTypeDictionaryKeyCallBacks
,
143 &kCFTypeDictionaryValueCallBacks
);
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
);
152 is_status(SecItemUpdate(query
, attrs
),
153 errSecSuccess
, "SecItemUpdate sync=true");
155 CFReleaseSafe(query
);
156 CFReleaseSafe(attrs
);
159 /* Test finding the updated item with its new attribute */
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
,
169 CFSTR("Updated Comment"),
170 kCFBooleanTrue
}; // we only want to find the synchronizable item here, not a non-synchronizable one
172 query
= CFDictionaryCreate(NULL
, keys
, values
,
174 &kCFTypeDictionaryKeyCallBacks
,
175 &kCFTypeDictionaryValueCallBacks
);
177 is_status(SecItemCopyMatching(query
, (CFTypeRef
*)&result
),
178 errSecSuccess
, "SecItemCopyMatching post-update");
180 CFReleaseSafe(result
);
181 // re-use query in next test...
184 /* Test deleting the item */
186 is_status(SecItemDelete(query
), errSecSuccess
, "SecItemDelete sync=true");
188 CFReleaseSafe(query
);
192 int si_72_syncableitems(int argc
, char * const *argv
)