]> git.saurik.com Git - apple/security.git/blob - keychain/securityd/Regressions/SOSTransportTestTransports.m
Security-59306.61.1.tar.gz
[apple/security.git] / keychain / securityd / Regressions / SOSTransportTestTransports.m
1 #include <CoreFoundation/CoreFoundation.h>
2 #include <CoreFoundation/CFRuntime.h>
3
4 #include "keychain/SecureObjectSync/SOSAccount.h"
5 #include "keychain/SecureObjectSync/SOSAccountPriv.h"
6 #include "keychain/SecureObjectSync/SOSTransport.h"
7 #import "keychain/SecureObjectSync/SOSTransportKeyParameter.h"
8 #import "keychain/SecureObjectSync/SOSTransportCircleKVS.h"
9 #import "keychain/SecureObjectSync/SOSTransportMessageKVS.h"
10 #include "keychain/SecureObjectSync/SOSKVSKeys.h"
11 #include "keychain/SecureObjectSync/SOSPeerCoder.h"
12 #include <utilities/SecCFWrappers.h>
13 #include "keychain/SecureObjectSync/SOSPeerInfoV2.h"
14 #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h"
15 #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h"
16
17 #include "SOSTransportTestTransports.h"
18 #include "SOSAccountTesting.h"
19
20 CFMutableArrayRef key_transports = NULL;
21 CFMutableArrayRef circle_transports = NULL;
22 CFMutableArrayRef message_transports = NULL;
23
24 ///
25 //Mark Test Key Parameter Transport
26 ///
27
28 @implementation CKKeyParameterTest
29
30 -(id) initWithAccount:(SOSAccount*) acct andName:(CFStringRef) n andCircleName:(CFStringRef) cN
31 {
32 self = [super init];
33 if(self){
34 self.name = CFRetainSafe(n);
35 self.changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
36 self.account = acct;
37 self.circleName = CFRetainSafe(cN);
38
39 if(!key_transports)
40 key_transports = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
41 CFArrayAppendValue(key_transports, (__bridge CFTypeRef)((CKKeyParameter*)self));
42
43 SOSRegisterTransportKeyParameter((CKKeyParameter*)self);
44 }
45 return self;
46 }
47
48 -(void)dealloc {
49 if(self) {
50 CFReleaseNull(self->_changes);
51 CFReleaseNull(self->_circleName);
52 }
53 }
54
55 - (void)setChanges:(CFMutableDictionaryRef)changes
56 {
57 CFRetainAssign(self->_changes, changes);
58 }
59
60 -(bool) SOSTransportKeyParameterHandleKeyParameterChanges:(CKKeyParameterTest*) transport data:(CFDataRef) data err:(CFErrorRef) error
61 {
62 SOSAccount* acct = transport.account;
63 return SOSAccountHandleParametersChange(acct, data, &error);
64 }
65
66
67 -(void) SOSTransportKeyParameterHandleNewAccount:(CKKeyParameterTest*) transport acct:(SOSAccount*) acct
68 {
69
70 if(key_transports){
71 CFArrayRemoveAllValue(key_transports, (__bridge CFTypeRef)(acct.key_transport));
72 }
73 if(message_transports){
74 CFArrayRemoveAllValue(message_transports, (__bridge CFTypeRef)acct.kvs_message_transport);
75 }
76 if(circle_transports)
77 CFArrayRemoveAllValue(circle_transports, (__bridge CFTypeRef)(acct.circle_transport));
78
79 SOSAccountSetToNew(acct);
80 SOSAccountResetToTest(acct, transport.name);
81 }
82
83 CFStringRef SOSTransportKeyParameterTestGetName(CKKeyParameterTest* transport){
84 return transport.name;
85 }
86
87 void SOSTransportKeyParameterTestSetName(CKKeyParameterTest* transport, CFStringRef accountName){
88 transport.name = accountName;
89 }
90
91 SOSAccount* SOSTransportKeyParameterTestGetAccount(CKKeyParameterTest* transport){
92 return ((CKKeyParameter*)transport).account;
93 }
94
95 CFMutableDictionaryRef SOSTransportKeyParameterTestGetChanges(CKKeyParameterTest* transport){
96 return transport.changes;
97 }
98
99 void SOSTransportKeyParameterTestClearChanges(CKKeyParameterTest* transport){
100 transport.changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
101 }
102
103 -(bool) SOSTransportKeyParameterPublishCloudParameters:(CKKeyParameterTest*) transport data:(CFDataRef)newParameters err:(CFErrorRef*) error
104 {
105 if(!transport.changes)
106 transport.changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
107
108 CFDictionarySetValue(transport.changes, kSOSKVSKeyParametersKey, newParameters);
109
110 return true;
111 }
112 @end
113
114
115 ///
116 //MARK: Test Circle Transport
117 ///
118 @implementation SOSCircleStorageTransportTest
119 @synthesize accountName = accountName;
120
121 -(id)init
122 {
123 return [super init];
124 }
125
126 CFStringRef SOSTransportCircleTestGetName(SOSCircleStorageTransportTest* transport){
127 return (__bridge CFStringRef)(transport.accountName);
128 }
129 void SOSTransportCircleTestSetName(SOSCircleStorageTransportTest* transport, CFStringRef name){
130 transport.accountName = nil;
131 transport.accountName = (__bridge NSString *)(name);
132 }
133
134 -(CFMutableDictionaryRef) SOSTransportCircleTestGetChanges
135 {
136 return (__bridge CFMutableDictionaryRef)(self.pending_changes);
137 }
138
139 void SOSTransportCircleTestClearChanges(SOSCircleStorageTransportTest* transport){
140 transport.pending_changes = [NSMutableDictionary dictionary];
141 }
142
143 -(id) initWithAccount:(SOSAccount *)acct andWithAccountName:(CFStringRef)acctName andCircleName:(CFStringRef)cName
144 {
145 self = [super init];
146 if(self){
147 self.account = acct;
148 self.accountName = (__bridge NSString *)(acctName);
149 self.circleName = (__bridge NSString*)cName;
150 self.pending_changes = [NSMutableDictionary dictionary];
151 if(!circle_transports)
152 circle_transports = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
153 CFArrayAppendValue(circle_transports, (__bridge CFTypeRef)self);
154
155 SOSRegisterTransportCircle((SOSCircleStorageTransportTest*)self);
156 }
157 return self;
158 }
159
160 -(bool) kvsRingFlushChanges:(CFErrorRef*) error
161 {
162 return true;
163 }
164
165 -(bool) kvsRingPostRing:(CFStringRef) ringName ring:(CFDataRef) ring err:(CFErrorRef *)error
166 {
167 CFStringRef ringKey = SOSRingKeyCreateWithName(ringName, error);
168 CFMutableDictionaryRef changes = [self SOSTransportCircleTestGetChanges];
169 CFDictionaryAddValue(changes, ringKey, ring);
170 CFReleaseNull(ringKey);
171 return true;
172 }
173
174 -(bool) kvssendDebugInfo:(CFStringRef) type debug:(CFTypeRef) debugInfo err:(CFErrorRef *)error
175 {
176 CFMutableDictionaryRef changes = [self SOSTransportCircleTestGetChanges];
177 CFDictionaryAddValue(changes, type, debugInfo);
178 return true;
179 }
180
181 -(bool) postRetirement:(CFStringRef)cName peer:(SOSPeerInfoRef)peer err:(CFErrorRef *)error
182 {
183 CFStringRef retirement_key = SOSRetirementKeyCreateWithCircleNameAndPeer(cName, SOSPeerInfoGetPeerID(peer));
184 CFDataRef retirement_data = SOSPeerInfoCopyEncodedData(peer, kCFAllocatorDefault, error);
185
186 if (retirement_key)
187 [self testAddToChanges:retirement_key data:retirement_data];
188
189 CFReleaseNull(retirement_key);
190 CFReleaseNull(retirement_data);
191 return true;
192 }
193
194 -(bool) flushChanges:(CFErrorRef *)error
195 {
196 return true;
197 }
198
199 -(void) testAddToChanges:(CFStringRef) message_key data:(CFDataRef) message_data
200 {
201 if (self.pending_changes == NULL) {
202 self.pending_changes = [NSMutableDictionary dictionary];
203 }
204 if (message_data == NULL) {
205 [self.pending_changes setObject:[NSNull null] forKey:(__bridge NSString*)(message_key)];
206 } else {
207 [self.pending_changes setObject:(__bridge NSData*)message_data forKey:(__bridge NSString*)message_key];
208 }
209 secnotice("circle-changes", "Adding circle change %@ %@->%@", self.accountName, message_key, message_data);
210 }
211
212 -(void) SOSTransportCircleTestAddBulkToChanges:(CFDictionaryRef) updates
213 {
214 if (self.pending_changes == NULL) {
215 self.pending_changes = [[NSMutableDictionary alloc]initWithDictionary:(__bridge NSDictionary * _Nonnull)(updates)];
216
217 }
218 else{
219 CFDictionaryForEach(updates, ^(const void *key, const void *value) {
220 [self.pending_changes setObject:(__bridge id _Nonnull)value forKey:(__bridge id _Nonnull)key];
221 });
222 }
223 }
224
225
226 -(bool) expireRetirementRecords:(CFDictionaryRef) retirements err:(CFErrorRef *)error
227 {
228 bool success = true;
229 CFMutableDictionaryRef keysToWrite = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
230
231 CFDictionaryForEach(retirements, ^(const void *key, const void *value) {
232 if (isString(key) && isArray(value)) {
233 CFStringRef circle_name = (CFStringRef) key;
234 CFArrayRef retirees = (CFArrayRef) value;
235
236 CFArrayForEach(retirees, ^(const void *value) {
237 if (isString(value)) {
238 CFStringRef retiree_id = (CFStringRef) value;
239
240 CFStringRef kvsKey = SOSRetirementKeyCreateWithCircleNameAndPeer(circle_name, retiree_id);
241
242 CFDictionaryAddValue(keysToWrite, kvsKey, kCFNull);
243
244 CFReleaseSafe(kvsKey);
245 }
246 });
247 }
248 });
249
250 if(CFDictionaryGetCount(keysToWrite)) {
251 [self SOSTransportCircleTestAddBulkToChanges:keysToWrite];
252 }
253 CFReleaseNull(keysToWrite);
254
255 return success;
256 }
257
258 bool SOSTransportCircleTestRemovePendingChange(SOSCircleStorageTransportTest* transport, CFStringRef circleName, CFErrorRef *error){
259 CFStringRef circle_key = SOSCircleKeyCreateWithName(circleName, error);
260 if (circle_key)
261 [transport.pending_changes removeObjectForKey:(__bridge NSString*)circle_key];
262 CFReleaseNull(circle_key);
263 return true;
264 }
265
266 -(bool) postCircle:(CFStringRef)cName circleData:(CFDataRef)circle_data err:(CFErrorRef *)error
267 {
268 CFStringRef circle_key = SOSCircleKeyCreateWithName(cName, error);
269 if (circle_key)
270 [self testAddToChanges:circle_key data:circle_data];
271 CFReleaseNull(circle_key);
272
273 return true;
274 }
275
276 -(CFDictionaryRef)handleRetirementMessages:(CFMutableDictionaryRef) circle_retirement_messages_table err:(CFErrorRef *)error
277 {
278 return SOSAccountHandleRetirementMessages(self.account, circle_retirement_messages_table, error);
279 }
280
281 -(CFArrayRef)CF_RETURNS_RETAINED handleCircleMessagesAndReturnHandledCopy:(CFMutableDictionaryRef) circle_circle_messages_table err:(CFErrorRef *)error
282 {
283 CFMutableArrayRef handledKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
284 CFDictionaryForEach(circle_circle_messages_table, ^(const void *key, const void *value) {
285 CFErrorRef circleMessageError = NULL;
286 if (!SOSAccountHandleCircleMessage(self.account, key, value, &circleMessageError)) {
287 secerror("Error handling circle message %@ (%@): %@", key, value, circleMessageError);
288 }
289 else{
290 CFStringRef circle_id = (CFStringRef) key;
291 CFArrayAppendValue(handledKeys, circle_id);
292 }
293 CFReleaseNull(circleMessageError);
294 });
295
296 return handledKeys;
297 }
298
299 SOSAccount* SOSTransportCircleTestGetAccount(SOSCircleStorageTransportTest* transport) {
300 return transport.account;
301 }
302
303 @end
304
305 ///
306 //MARK KVS Message Test Transport
307 ///
308
309
310
311 @implementation SOSMessageKVSTest
312
313
314 -(id) initWithAccount:(SOSAccount*)acct andName:(CFStringRef)n andCircleName:(CFStringRef) cN
315 {
316 self = [super init];
317 if(self){
318 self.engine = SOSDataSourceFactoryGetEngineForDataSourceName(acct.factory, cN, NULL);
319 self.account = acct;
320 self.changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
321 self.name = CFRetainSafe(n);
322 self.circleName = (__bridge NSString*)cN;
323
324 if(!message_transports)
325 message_transports = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
326 CFArrayAppendValue(message_transports, (__bridge const void *)((SOSMessageKVSTest*)self));
327 SOSRegisterTransportMessage((SOSMessageKVSTest*)self);
328 }
329
330 return self;
331 }
332
333 - (void)setChanges:(CFMutableDictionaryRef)changes
334 {
335 CFRetainAssign(self->_changes, changes);
336 }
337
338 -(CFIndex) SOSTransportMessageGetTransportType
339 {
340 return kKVSTest;
341 }
342 -(CFStringRef) SOSTransportMessageGetCircleName
343 {
344 return (__bridge CFStringRef)circleName;
345 }
346 -(CFTypeRef) SOSTransportMessageGetEngine
347 {
348 return engine;
349 }
350 -(SOSAccount*) SOSTransportMessageGetAccount
351 {
352 return self.account;
353 }
354
355 void SOSTransportMessageKVSTestSetName(SOSMessageKVSTest* transport, CFStringRef n)
356 {
357 transport.name = n;
358 }
359
360 CFStringRef SOSTransportMessageKVSTestGetName(SOSMessageKVSTest* transport)
361 {
362 return transport.name;
363 }
364
365 CFMutableDictionaryRef SOSTransportMessageKVSTestGetChanges(SOSMessageKVSTest* transport)
366 {
367 return transport.changes;
368 }
369
370 void SOSTransportMessageTestClearChanges(SOSMessageKVSTest* transport)
371 {
372 transport.changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
373 }
374
375 static void SOSTransportMessageTestAddBulkToChanges(SOSMessageKVSTest* transport, CFDictionaryRef updates)
376 {
377 #ifndef __clang_analyzer__ // The analyzer thinks transport.changes is a leak, but I don't know why.
378 if (transport.changes == NULL) {
379 transport.changes = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(updates), updates);
380 }
381 else{
382 CFDictionaryForEach(updates, ^(const void *key, const void *value) {
383 CFDictionarySetValue(transport.changes, key, value);
384 });
385 }
386 #endif // __clang_analyzer__
387 }
388
389 static void SOSTransportMessageTestAddToChanges(SOSMessageKVSTest* transport, CFStringRef message_key, CFDataRef message_data)
390 {
391 if (transport.changes == NULL) {
392 transport.changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
393 }
394 if (message_data == NULL) {
395 CFDictionarySetValue(transport.changes, message_key, kCFNull);
396 } else {
397 CFDictionarySetValue(transport.changes, message_key, message_data);
398 }
399 }
400
401 -(bool) SOSTransportMessageCleanupAfterPeerMessages:(SOSMessageKVSTest*) transport peers:(CFDictionaryRef)circle_to_peer_ids err:(CFErrorRef*) error
402 {
403 if(!transport.engine)
404 return true;
405 CFArrayRef enginePeers = SOSEngineGetPeerIDs((SOSEngineRef)transport.engine);
406
407 CFDictionaryForEach(circle_to_peer_ids, ^(const void *key, const void *value) {
408 if (isString(key) && isArray(value)) {
409 CFStringRef circle_name = (CFStringRef) key;
410 CFArrayRef peers_to_cleanup_after = (CFArrayRef) value;
411
412 CFArrayForEach(peers_to_cleanup_after, ^(const void *value) {
413 if (isString(value)) {
414 CFStringRef cleanup_id = (CFStringRef) value;
415 // TODO: Since the enginePeers list is not authorative (the Account is) this could inadvertently clean up active peers or leave behind stale peers
416 if (enginePeers) CFArrayForEach(enginePeers, ^(const void *value) {
417 if (isString(value)) {
418 CFStringRef in_circle_id = (CFStringRef) value;
419
420 CFStringRef kvsKey = SOSMessageKeyCreateWithCircleNameAndPeerNames(circle_name, cleanup_id, in_circle_id);
421 SOSTransportMessageTestAddToChanges(transport, kvsKey, NULL);
422 CFReleaseSafe(kvsKey);
423
424 kvsKey = SOSMessageKeyCreateWithCircleNameAndPeerNames(circle_name, in_circle_id, cleanup_id);
425 SOSTransportMessageTestAddToChanges(transport, kvsKey, NULL);
426 CFReleaseSafe(kvsKey);
427 }
428 });
429
430 }
431 });
432 }
433 });
434
435 return [transport SOSTransportMessageFlushChanges:transport err:error];
436 return true;
437 }
438
439 static bool sendToPeer(SOSMessageKVSTest* transport, CFStringRef circleName, CFStringRef peerID, CFDataRef message, CFErrorRef *error) {
440 bool result = true;
441 NSString* myID = transport.account.peerID;
442 CFStringRef message_to_peer_key = SOSMessageKeyCreateFromTransportToPeer((SOSMessage*)transport, (__bridge CFStringRef) myID, peerID);
443 CFDictionaryRef a_message_to_a_peer = CFDictionaryCreateForCFTypes(NULL, message_to_peer_key, message, NULL);
444
445 SOSTransportMessageTestAddBulkToChanges(transport, a_message_to_a_peer);
446 CFReleaseNull(a_message_to_a_peer);
447 CFReleaseNull(message_to_peer_key);
448
449 return result;
450 }
451
452 -(bool) SOSTransportMessageSyncWithPeers:(SOSMessageKVSTest*) transport p:(CFSetRef) peers err:(CFErrorRef *)error
453 {
454 // Each entry is keyed by circle name and contains a list of peerIDs
455
456 __block bool result = true;
457
458 CFSetForEach(peers, ^(const void *value) {
459 CFStringRef peerID = asString(value, NULL);
460
461 if (peerID) {
462 SOSEngineWithPeerID((SOSEngineRef)transport.engine, peerID, error, ^(SOSPeerRef peer, SOSCoderRef coder, SOSDataSourceRef dataSource, SOSTransactionRef txn, bool *forceSaveState) {
463 SOSEnginePeerMessageSentCallback* sentCallback = NULL;
464 CFDataRef message_to_send = NULL;
465 bool ok = SOSPeerCoderSendMessageIfNeeded([transport SOSTransportMessageGetAccount], (SOSEngineRef)transport.engine, txn, peer, coder, &message_to_send, peerID, false, &sentCallback, error);
466 if (message_to_send) {
467 CFDictionaryRef peer_dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, peerID, message_to_send, NULL);
468 CFDictionarySetValue(SOSTransportMessageKVSTestGetChanges(transport), (__bridge CFStringRef)self->circleName, peer_dict);
469 SOSEngineMessageCallCallback(sentCallback, ok);
470 CFReleaseSafe(peer_dict);
471 }
472
473 SOSEngineFreeMessageCallback(sentCallback);
474 CFReleaseSafe(message_to_send);
475 });
476 }
477 });
478 return result;
479 }
480
481 -(bool) SOSTransportMessageSendMessages:(SOSMessageKVSTest*) transport pm:(CFDictionaryRef) peer_messages err:(CFErrorRef *)error
482 {
483 __block bool result = true;
484
485 CFDictionaryForEach(peer_messages, ^(const void *key, const void *value) {
486 if (isString(key) && isData(value)) {
487 CFStringRef peerID = (CFStringRef) key;
488 CFDataRef message = (CFDataRef) value;
489 bool rx = sendToPeer(transport, (__bridge CFStringRef)transport->circleName, peerID, message, error);
490 result &= rx;
491 }
492 });
493
494 return result;
495 }
496
497 -(bool) SOSTransportMessageFlushChanges:(SOSMessageKVSTest*) transport err:(CFErrorRef *)error
498 {
499 return true;
500 }
501
502 SOSAccount* SOSTransportMessageKVSTestGetAccount(SOSMessageKVSTest* transport) {
503 return transport.account;
504 }
505 @end
506
507
508 void SOSAccountUpdateTestTransports(SOSAccount* account, CFDictionaryRef gestalt){
509 CFStringRef new_name = (CFStringRef)CFDictionaryGetValue(gestalt, kPIUserDefinedDeviceNameKey);
510
511 SOSTransportKeyParameterTestSetName((CKKeyParameterTest*)account.key_transport, new_name);
512 SOSTransportCircleTestSetName((SOSCircleStorageTransportTest*)account.circle_transport, new_name);
513 SOSTransportMessageKVSTestSetName((SOSMessageKVSTest*)account.kvs_message_transport, new_name);
514 }
515
516 static CF_RETURNS_RETAINED SOSCircleRef SOSAccountEnsureCircleTest(SOSAccount* a, CFStringRef name, CFStringRef accountName)
517 {
518 CFErrorRef localError = NULL;
519 SOSAccountTrustClassic *trust = a.trust;
520
521 SOSCircleRef circle = CFRetainSafe([a.trust getCircle:&localError]);
522 if(!circle || isSOSErrorCoded(localError, kSOSErrorIncompatibleCircle)){
523 secnotice("circle", "Error retrieving the circle: %@", localError);
524 CFReleaseNull(localError);
525 CFReleaseNull(circle);
526
527 circle = SOSCircleCreate(kCFAllocatorDefault, name, &localError);
528 if (circle){
529 [trust setTrustedCircle:circle];
530 }
531 else{
532 secnotice("circle", "Could not create circle: %@", localError);
533 }
534 CFReleaseNull(localError);
535 }
536
537 if(![trust ensureFullPeerAvailable:(__bridge CFDictionaryRef)(a.gestalt) deviceID:(__bridge CFStringRef)(a.deviceID) backupKey:(__bridge CFDataRef)(a.backup_key) err:&localError])
538 {
539 secnotice("circle", "had an error building full peer: %@", localError);
540 CFReleaseNull(localError);
541 return circle;
542 }
543
544 CFReleaseNull(localError);
545 return circle;
546 }
547
548 bool SOSAccountEnsureFactoryCirclesTest(SOSAccount* a, CFStringRef accountName)
549 {
550 bool result = false;
551 if (a)
552 {
553 if(!a.factory)
554 return result;
555 CFStringRef circle_name = SOSDataSourceFactoryCopyName(a.factory);
556 if(!circle_name)
557 return result;
558 CFReleaseSafe(SOSAccountEnsureCircleTest(a, (CFStringRef)circle_name, accountName));
559
560 CFReleaseNull(circle_name);
561 result = true;
562 }
563 return result;
564 }
565
566 bool SOSAccountInflateTestTransportsForCircle(SOSAccount* account, CFStringRef circleName, CFStringRef accountName, CFErrorRef *error){
567 bool success = false;
568
569 if(account.key_transport == nil){
570 account.key_transport = (CKKeyParameter*)[[CKKeyParameterTest alloc] initWithAccount:account andName:accountName andCircleName:circleName];
571 require_quiet(account.key_transport, fail);
572 }
573
574 if(account.circle_transport == nil){
575 account.circle_transport = (SOSKVSCircleStorageTransport*)[[SOSCircleStorageTransportTest alloc] initWithAccount:account andWithAccountName:accountName andCircleName:circleName];
576 require_quiet(account.circle_transport, fail);
577 }
578 if(account.kvs_message_transport == nil){
579 account.kvs_message_transport = (SOSMessageKVS*)[[SOSMessageKVSTest alloc] initWithAccount:account andName:accountName andCircleName:circleName];
580 }
581
582 success = true;
583 fail:
584 return success;
585 }
586
587