3 // si-72-syncableitems.c
6 // Created by Ken McLeod on 5/18/13.
9 #include <CoreFoundation/CoreFoundation.h>
10 #include <Security/Security.h>
11 #include <Security/SecItemPriv.h>
12 #include <Security/SecInternal.h>
13 #include <utilities/array_size.h>
15 #include "Security_regressions.h"
17 static void tests(void)
19 CFUUIDRef uuid
= CFUUIDCreate(0);
20 const CFStringRef uuidstr
= CFUUIDCreateString(0, uuid
);
21 const CFStringRef account
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("Test Account %@"), uuidstr
);
22 const CFStringRef service
= CFSTR("Test Service");
23 const CFStringRef label
= CFSTR("Test Synchronizable Item");
24 const CFStringRef comment
= CFSTR("Test Comment");
25 const CFDataRef passwordData
= CFDataCreate(NULL
, (const UInt8
*)"Test", (CFIndex
)5);
28 CFReleaseSafe(uuidstr
);
30 CFDictionaryRef query
= NULL
;
31 CFDictionaryRef attrs
= NULL
;
32 CFDictionaryRef result
= NULL
;
34 /* Test adding a synchronizable item */
36 const void *keys
[] = {
37 kSecClass
, kSecAttrLabel
, kSecAttrComment
, kSecAttrAccount
, kSecAttrService
,
38 kSecAttrSynchronizable
,
39 kSecValueData
, kSecReturnAttributes
};
40 const void *values
[] = {
41 kSecClassGenericPassword
, label
, comment
, account
, service
,
43 passwordData
, kCFBooleanTrue
};
45 attrs
= CFDictionaryCreate(NULL
, keys
, values
,
47 &kCFTypeDictionaryKeyCallBacks
,
48 &kCFTypeDictionaryValueCallBacks
);
50 is_status(SecItemAdd(attrs
, (CFTypeRef
*)&result
),
51 errSecSuccess
, "SecItemAdd sync=true");
54 CFReleaseNull(result
);
57 /* Test finding the synchronizable item we just added, using sync=true */
59 const void *keys
[] = {
60 kSecClass
, // class attribute is required
61 kSecAttrAccount
, kSecAttrService
, // we'll look up by account and service, which determine uniqueness
62 kSecAttrSynchronizable
, // we want to get synchronizable results
63 kSecReturnAttributes
};
64 const void *values
[] = {
65 kSecClassGenericPassword
,
67 kCFBooleanTrue
, // only return synchronizable results
70 query
= CFDictionaryCreate(NULL
, keys
, values
,
72 &kCFTypeDictionaryKeyCallBacks
,
73 &kCFTypeDictionaryValueCallBacks
);
75 is_status(SecItemCopyMatching(query
, (CFTypeRef
*)&result
),
76 errSecSuccess
, "SecItemCopyMatching sync=true");
79 CFReleaseNull(result
);
82 /* Test finding the synchronizable item we just added, using sync=any */
84 const void *keys
[] = {
85 kSecClass
, // class attribute is required
86 kSecAttrAccount
, kSecAttrService
, // we'll look up by account and service, which determine uniqueness
87 kSecAttrSynchronizable
, // we want to get synchronizable results
88 kSecReturnAttributes
};
89 const void *values
[] = {
90 kSecClassGenericPassword
,
92 kSecAttrSynchronizableAny
, // return any match, regardless of whether it is synchronizable
95 query
= CFDictionaryCreate(NULL
, keys
, values
,
97 &kCFTypeDictionaryKeyCallBacks
,
98 &kCFTypeDictionaryValueCallBacks
);
100 is_status(SecItemCopyMatching(query
, (CFTypeRef
*)&result
),
101 errSecSuccess
, "SecItemCopyMatching sync=any");
103 CFReleaseSafe(query
);
104 CFReleaseNull(result
);
107 /* Test updating the synchronizable item */
109 const void *keys
[] = {
110 kSecClass
, // class attribute is required
111 kSecAttrAccount
, kSecAttrService
, // we'll look up by account and service, which determine uniqueness
112 kSecAttrSynchronizable
}; // we want synchronizable results
113 const void *values
[] = {
114 kSecClassGenericPassword
,
116 kCFBooleanTrue
}; // we only want to find the synchronizable item here, not a non-synchronizable one
118 query
= CFDictionaryCreate(NULL
, keys
, values
,
120 &kCFTypeDictionaryKeyCallBacks
,
121 &kCFTypeDictionaryValueCallBacks
);
123 const void *update_keys
[] = { kSecAttrComment
};
124 const void *update_values
[] = { CFSTR("Updated Comment") };
125 attrs
= CFDictionaryCreate(NULL
, update_keys
, update_values
,
126 array_size(update_keys
),
127 &kCFTypeDictionaryKeyCallBacks
,
128 &kCFTypeDictionaryValueCallBacks
);
130 is_status(SecItemUpdate(query
, attrs
),
131 errSecSuccess
, "SecItemUpdate sync=true");
133 CFReleaseSafe(query
);
134 CFReleaseSafe(attrs
);
137 /* Test finding the updated item with its new attribute */
139 const void *keys
[] = {
140 kSecClass
, // class attribute is required
141 kSecAttrAccount
, kSecAttrService
, // we'll look up by account and service, which determine uniqueness
142 kSecAttrComment
, // also search on the attr we just changed, so we know we've found the updated item
143 kSecAttrSynchronizable
}; // we want synchronizable results
144 const void *values
[] = {
145 kSecClassGenericPassword
,
147 CFSTR("Updated Comment"),
148 kCFBooleanTrue
}; // we only want to find the synchronizable item here, not a non-synchronizable one
150 query
= CFDictionaryCreate(NULL
, keys
, values
,
152 &kCFTypeDictionaryKeyCallBacks
,
153 &kCFTypeDictionaryValueCallBacks
);
155 is_status(SecItemCopyMatching(query
, (CFTypeRef
*)&result
),
156 errSecSuccess
, "SecItemCopyMatching post-update");
158 CFReleaseSafe(result
);
159 // re-use query in next test...
162 /* Test deleting the item */
164 is_status(SecItemDelete(query
), errSecSuccess
, "SecItemDelete sync=true");
166 CFReleaseSafe(query
);
170 int si_72_syncableitems(int argc
, char * const *argv
)