]> git.saurik.com Git - apple/security.git/blob - keychain/securityd/Regressions/secd-70-engine-corrupt.m
Security-59754.80.3.tar.gz
[apple/security.git] / keychain / securityd / Regressions / secd-70-engine-corrupt.m
1 /*
2 * Copyright (c) 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 // Test syncing between SecItemDataSource and SOSTestDataSource
26
27 #include "keychain/SecureObjectSync/Regressions/SOSTestDevice.h"
28 #include "keychain/SecureObjectSync/Regressions/SOSTestDataSource.h"
29 #include "secd_regressions.h"
30 #include "SecdTestKeychainUtilities.h"
31
32 #include "keychain/SecureObjectSync/SOSDigestVector.h"
33 #include "keychain/SecureObjectSync/SOSEngine.h"
34 #include "keychain/SecureObjectSync/SOSPeer.h"
35 #import "keychain/SecureObjectSync/SOSChangeTracker.h"
36 #include <Security/SecBase64.h>
37 #include <Security/SecItem.h>
38 #include <Security/SecItemPriv.h>
39 #include <corecrypto/ccsha2.h>
40 #include "keychain/securityd/SecItemServer.h"
41 #include "keychain/securityd/SecItemDataSource.h"
42 #include <utilities/SecCFWrappers.h>
43 #include <utilities/SecIOFormat.h>
44 #include <utilities/SecFileLocations.h>
45 #include "SOSAccountTesting.h"
46
47 #include <AssertMacros.h>
48 #include <stdint.h>
49 #if SOS_ENABLED
50
51 static int kTestTestCount = 121;
52
53 static void nosha1(void) {
54 __block int iteration = 0;
55 __block CFErrorRef error = NULL;
56 SOSTestDeviceListTestSync("nosha1", test_directive, test_reason, 0, true, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) {
57 iteration++;
58 // Add 10 items in first 10 sync messages
59 if (iteration <= 6) {
60 CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration);
61 SOSTestDeviceAddGenericItem(source, account, CFSTR("nosha1"));
62 CFReleaseSafe(account);
63 // Corrupt the 4th item added
64 if (iteration == 4) {
65 ok(SecDbPerformWrite(source->db, &error, ^(SecDbConnectionRef dbconn) {
66 ok(SecDbTransaction(dbconn, kSecDbExclusiveTransactionType, &error, ^(bool *commit) {
67 ok(SecDbExec(dbconn, CFSTR("UPDATE genp SET sha1=X'0000000000000000000000000000000000000000' WHERE rowid=5;"), &error),
68 "Corrupting rowid 5 by zeroing sha1: %@", error);
69 CFReleaseNull(error);
70 }), "SecDbTransaction: %@", error);
71 CFReleaseNull(error);
72 }), "SecDbPerformWrite: %@", error);
73 CFReleaseNull(error);
74 return true;
75 }
76 return true;
77 }
78
79
80 return false;
81 }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) {
82 return false;
83 }, CFSTR("Bad"), CFSTR("Good"), NULL);
84 }
85
86 static void drop_item(void) {
87 __block int iteration = 0;
88 __block CFErrorRef error = NULL;
89 SOSTestDeviceListTestSync("drop_item", test_directive, test_reason, 0, true, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) {
90 iteration++;
91 // Add 10 items in first 10 sync messages
92 if (iteration <= 6) {
93 CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration);
94 SOSTestDeviceAddGenericItem(source, account, CFSTR("drop_item"));
95 CFReleaseSafe(account);
96 // Corrupt the 4th item added
97 if (iteration == 4) {
98 ok(SecDbPerformWrite(source->db, &error, ^(SecDbConnectionRef dbconn) {
99 ok(SecDbTransaction(dbconn, kSecDbExclusiveTransactionType, &error, ^(bool *commit) {
100 ok(SecDbExec(dbconn, CFSTR("DELETE FROM genp WHERE rowid=5;"), &error),
101 "Corrupting rowid 5 by deleting object: %@", error);
102 CFReleaseNull(error);
103 }), "SecDbTransaction: %@", error);
104 CFReleaseNull(error);
105 }), "SecDbPerformWrite: %@", error);
106 CFReleaseNull(error);
107 return true;
108 }
109 return true;
110 }
111
112
113 return false;
114 }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) {
115 return false;
116 }, CFSTR("Abegail"), CFSTR("Billy"), NULL);
117 }
118
119 static void drop_manifest(void) {
120 __block int iteration = 0;
121 SOSTestDeviceListTestSync("drop_manifest", test_directive, test_reason, 0, true, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) {
122 iteration++;
123 // Add 5 items on Alice and 4 on Bob in first 9 sync messages
124 if (iteration <= 9) {
125 CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration / 2);
126 SOSTestDeviceAddGenericItem(source, account, CFSTR("drop_manifest"));
127 CFReleaseSafe(account);
128 // Corrupt the manifest after 4th item added
129 if (iteration == 4) {
130 SOSEngineRef engine = SOSDataSourceGetSharedEngine(source->ds, NULL);
131 SOSPeerRef peer = SOSEngineCopyPeerWithID(engine, SOSTestDeviceGetID(dest), NULL);
132 SOSManifestRef mf = SOSEngineCopyLocalPeerManifest(engine, peer, NULL);
133 CFReleaseNull(peer);
134 CFMutableArrayRef changes = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
135 SOSManifestForEach(mf, ^(CFDataRef e, bool *stop) {
136 SOSChangesAppendDelete(changes, e);
137 });
138 ok(SOSEngineUpdateChanges(engine, kSOSDataSourceSOSTransaction, changes, NULL), "droped manifest from %@", source);
139 CFReleaseNull(changes);
140 CFReleaseNull(mf);
141 return true;
142 }
143 return true;
144 }
145
146 return false;
147 }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) {
148 return false;
149 }, CFSTR("Ann"), CFSTR("Ben"), NULL);
150 }
151
152 static void add_sha1(void) {
153 TODO: {
154 //todo("this never stops syncing");
155 __block int iteration = 0;
156 __block CFErrorRef error = NULL;
157 SOSTestDeviceListTestSync("add_sha1", test_directive, test_reason, 0, true, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) {
158 iteration++;
159 // Add 9 items in first 9 sync messages
160 if (iteration <= 9) {
161 CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration);
162 SOSTestDeviceAddGenericItem(source, account, CFSTR("add_sha1"));
163 CFReleaseSafe(account);
164 // Corrupt the manifest after 4th item added
165 if (iteration == 4) {
166 ok(SecDbPerformWrite(source->db, &error, ^(SecDbConnectionRef dbconn) {
167 ok(SecDbTransaction(dbconn, kSecDbExclusiveTransactionType, &error, ^(bool *commit) {
168 ok(SecDbExec(dbconn, CFSTR("UPDATE genp SET sha1=X'0000000000000000000000000000000000000000' WHERE rowid=5;"), &error),
169 "Corrupting rowid 5 by zeroing sha1: %@", error);
170 CFReleaseNull(error);
171 }), "SecDbTransaction: %@", error);
172 CFReleaseNull(error);
173 }), "SecDbPerformWrite: %@", error);
174 CFReleaseNull(error);
175
176 SOSEngineRef engine = SOSDataSourceGetSharedEngine(source->ds, NULL);
177 uint8_t zeroDigest[20] = {};
178 CFDataRef zDigest = CFDataCreate(kCFAllocatorDefault, zeroDigest, 20);
179 CFMutableArrayRef changes = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
180 SOSChangesAppendAdd(changes, zDigest);
181 ok(SOSEngineUpdateChanges(engine, kSOSDataSourceSOSTransaction, changes, NULL), "corrupting manifest");
182 CFReleaseSafe(zDigest);
183 CFReleaseNull(changes);
184 return true;
185 }
186 return true;
187 }
188
189 return false;
190 }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) {
191 return false;
192 }, CFSTR("Andy"), CFSTR("Bill"), NULL);
193 }
194 }
195
196 static void change_sha1(void) {
197 TODO: {
198 //todo("this never stops syncing");
199 __block int iteration = 0;
200 __block CFErrorRef error = NULL;
201 SOSTestDeviceListTestSync("change_sha1", test_directive, test_reason, 0, true, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) {
202 iteration++;
203 // Add 9 items in first 9 sync messages
204 if (iteration <= 9) {
205 CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration);
206 CFStringRef server = CFSTR("change_sha1");
207 // Corrupt the manifest after 4th item added
208 if (!SOSDataSourceWithAPI(source->ds, true, &error, ^(SOSTransactionRef txn, bool *commit) {
209 SOSObjectRef object = SOSDataSourceCreateGenericItem(source->ds, account, server);
210 ok(SOSDataSourceMergeObject(source->ds, txn, object, NULL, &error), "%@ added API object %@", SOSTestDeviceGetID(source), error ? (CFTypeRef)error : (CFTypeRef)CFSTR("ok"));
211 if (iteration == 3) {
212 sqlite_int64 rowid = SecDbItemGetRowId((SecDbItemRef)object, NULL);
213 CFStringRef sql = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("UPDATE genp SET sha1=X'0000000000000000000000000000000000000000' WHERE rowid=%lld;"), rowid);
214 ok(SecDbExec((SecDbConnectionRef)txn, sql, &error),
215 "Corrupting rowid %lld by zeroing sha1: %@", rowid, error);
216 CFReleaseNull(sql);
217 SOSEngineRef engine = SOSDataSourceGetSharedEngine(source->ds, NULL);
218 CFMutableArrayRef changes = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
219 uint8_t zeroDigest[20] = {};
220 CFDataRef zDigest = CFDataCreate(kCFAllocatorDefault, zeroDigest, 20);
221 SOSChangesAppendAdd(changes, zDigest);
222 CFDataRef digest = SOSObjectCopyDigest(source->ds, object, NULL);
223 SOSChangesAppendDelete(changes, digest);
224 const uint8_t *d = CFDataGetBytePtr(digest);
225 ok(SOSEngineUpdateChanges(engine, kSOSDataSourceSOSTransaction, changes, NULL), "corrupting manifest %lld %02X%02x%02x%02x",
226 rowid, d[0], d[1], d[2], d[3]);
227 CFReleaseSafe(zDigest);
228 CFReleaseSafe(digest);
229 CFReleaseNull(changes);
230 }
231 CFReleaseSafe(object);
232 CFReleaseNull(error);
233 }))
234 fail("ds transaction %@", error);
235 CFReleaseNull(error);
236 CFReleaseNull(account);
237 return true;
238 }
239 return false;
240 }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) {
241 if (iteration >= 3)
242 pass("%@", source);
243 return false;
244 }, CFSTR("Alice"), CFSTR("Bob"), NULL);
245 }
246 }
247 #endif
248
249 int secd_70_engine_corrupt(int argc, char *const *argv)
250 {
251 #if SOS_ENABLED
252 plan_tests(kTestTestCount);
253 __security_simulatecrash_enable(false);
254 /* custom keychain dir */
255 secd_test_setup_temp_keychain(__FUNCTION__, NULL);
256 nosha1();
257 drop_item();
258 drop_manifest();
259 add_sha1();
260 change_sha1();
261 __security_simulatecrash_enable(true);
262 #else
263 plan_tests(0);
264 #endif
265 return 0;
266 }