SOSAccountRef SOSAccountCreateFromDER_V1(CFAllocatorRef allocator, SOSDataSourceFactoryRef factory, CFErrorRef* error, const uint8_t** der_p, const uint8_t *der_end) { SOSAccountRef account = NULL; const uint8_t *sequence_end; *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); { CFDictionaryRef decoded_gestalt = NULL; *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, *der_p, der_end); if (*der_p == 0) return NULL; account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); CFReleaseNull(decoded_gestalt); } CFArrayRef array = NULL; *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); if (*der_p != sequence_end) *der_p = NULL; __block bool success = true; require_quiet(array && *der_p, fail); CFArrayForEach(array, ^(const void *value) { if (success) { if (isString(value)) { CFDictionaryAddValue(account->circles, value, kCFNull); } else { CFDataRef circleData = NULL; CFDataRef fullPeerInfoData = NULL; if (isData(value)) { circleData = (CFDataRef) value; } else if (isArray(value)) { CFArrayRef pair = (CFArrayRef) value; CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { circleData = (CFDataRef) circleObject; fullPeerInfoData = (CFDataRef) fullPeerInfoObject; } } if (circleData) { SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); require_action_quiet(circle, fail, success = false); CFStringRef circleName = SOSCircleGetName(circle); CFDictionaryAddValue(account->circles, circleName, circle); if (fullPeerInfoData) { SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); require_action_quiet(full_peer, fail, success = false); CFDictionaryAddValue(account->circle_identities, circleName, full_peer); CFReleaseNull(full_peer); } fail: CFReleaseNull(circle); } } } });
static void tests() { CFErrorRef error = NULL; CFStringRef aliceID = CFSTR("Alice"); CFStringRef bobID = CFSTR("Bob"); // not really remote, just another client on same machine SecKeyRef alice_key = NULL; SecKeyRef bob_key = NULL; CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); CFDataRef parameters = SOSUserKeyCreateGenerateParameters(&error); ok(parameters, "No parameters!"); ok(error == NULL, "Error: (%@)", error); CFReleaseNull(error); SecKeyRef user_privkey = SOSUserKeygen(cfpassword, parameters, &error); CFReleaseNull(parameters); CFReleaseSafe(cfpassword); CFStringRef circleName = CFSTR("Woot Circle"); SOSFullPeerInfoRef alice_full_peer_info = SOSCreateFullPeerInfoFromName(aliceID, &alice_key, &error); SOSPeerInfoRef alice_peer_info = SOSFullPeerInfoGetPeerInfo(alice_full_peer_info); SOSFullPeerInfoRef bob_full_peer_info = SOSCreateFullPeerInfoFromName(bobID, &bob_key, &error); SOSPeerInfoRef bob_peer_info = SOSFullPeerInfoGetPeerInfo(bob_full_peer_info); SOSCircleRef aliceCircle = SOSCircleCreate(kCFAllocatorDefault, circleName, &error); ok(SOSCircleRequestAdmission(aliceCircle, user_privkey, alice_full_peer_info, &error)); ok(SOSCircleAcceptRequests(aliceCircle, user_privkey, alice_full_peer_info, NULL)); ok(SOSCircleRequestAdmission(aliceCircle, user_privkey, bob_full_peer_info, &error), "requested admission"); ok(SOSCircleAcceptRequests(aliceCircle, user_privkey, bob_full_peer_info, &error), "accepted them all!"); alice_peer_info = SOSFullPeerInfoGetPeerInfo(alice_full_peer_info); bob_peer_info = SOSFullPeerInfoGetPeerInfo(bob_full_peer_info); CFDataRef aliceCircleEncoded; ok(aliceCircleEncoded = SOSCircleCopyEncodedData(aliceCircle, kCFAllocatorDefault, &error), "encode alice circle: %@", error); CFReleaseNull(error); SOSCircleRef bobCircle; ok(bobCircle = SOSCircleCreateFromData(0, aliceCircleEncoded, &error), "decode bobCircle: %@", error); CFReleaseNull(aliceCircleEncoded); CFReleaseNull(error); /* Transport. */ __block CFDataRef queued_message = NULL; SOSPeerSendBlock enqueueMessage = ^bool (CFDataRef message, CFErrorRef *error) { if (queued_message) fail("We already had an unproccessed message"); queued_message = (CFDataRef) CFRetain(message); return true; }; CFDataRef (^dequeueMessage)() = ^CFDataRef () { CFDataRef result = queued_message; queued_message = NULL; return result; }; /* DataSource */ SOSDataSourceRef aliceDs = SOSTestDataSourceCreate(); SOSDataSourceRef bobDs = SOSTestDataSourceCreate(); SOSDataSourceFactoryRef aliceDsf = SOSTestDataSourceFactoryCreate(); SOSTestDataSourceFactoryAddDataSource(aliceDsf, circleName, aliceDs); SOSDataSourceFactoryRef bobDsf = SOSTestDataSourceFactoryCreate(); SOSTestDataSourceFactoryAddDataSource(bobDsf, circleName, bobDs); /* Test passing peer messages to the engine. */ CFDataRef message; CFStringRef bob_peer_id = SOSPeerInfoGetPeerID(bob_peer_info); /* Hand an empty message to the engine for handeling. */ message = CFDataCreate(NULL, NULL, 0); is(SOSCircleHandlePeerMessage(aliceCircle, alice_full_peer_info, aliceDsf, enqueueMessage, bob_peer_id, message, &error), false, "empty message rejected, %@", error); CFReleaseNull(error); CFReleaseNull(message); ok(SOSCircleSyncWithPeer(alice_full_peer_info, aliceCircle, aliceDsf, enqueueMessage, bob_peer_id, &error), "Start sync [error %@]", error); CFReleaseNull(error); ok(message = dequeueMessage(), "Alice sent message"); CFStringRef alice_peer_id = SOSPeerInfoGetPeerID(alice_peer_info); is(SOSCircleHandlePeerMessage(bobCircle, bob_full_peer_info, bobDsf, enqueueMessage, alice_peer_id, message, &error), true, "Bob accepted message: %@", error); CFReleaseNull(message); #if 1 CFStringRef desc = NULL; ok(message = dequeueMessage(), "we got a message from Bob %@", desc = SOSMessageCopyDescription(message)); ok(SOSCircleHandlePeerMessage(aliceCircle, alice_full_peer_info, aliceDsf, enqueueMessage, bob_peer_id, message, &error), "Alice accepted message: %@", error); CFReleaseNull(message); CFReleaseNull(desc); ok(message = dequeueMessage(), "we got a reply from Alice %@", desc = SOSMessageCopyDescription(message)); ok(SOSCircleHandlePeerMessage(bobCircle, bob_full_peer_info, bobDsf, enqueueMessage, alice_peer_id, message, &error), "Bob accepted message: %@", error); CFReleaseNull(message); CFReleaseNull(desc); #endif #if 0 message = dequeueMessage(); ok(NULL == message, "we got no message from Bob %@", desc = SOSMessageCopyDescription(message)); SOSObjectRef object = SOSDataSourceCreateGenericItem(aliceDs, CFSTR("75_circle_engine_account"), CFSTR("test service")); ok(SOSTestDataSourceAddObject(aliceDs, object, &error), "add empty object to datasource: %@", error); CFReleaseNull(error); CFReleaseNull(object); ok(SOSCircleSyncWithPeer(alice_full_peer_info, aliceCircle, aliceDsf, enqueueMessage, bob_peer_id, &error), "Restart sync [error %@]", error); CFReleaseNull(error); ok(message = dequeueMessage(), "Alice started again %@", desc = SOSMessageCopyDescription(message)); is(SOSCircleHandlePeerMessage(bobCircle, bob_full_peer_info, bobDsf, enqueueMessage, alice_peer_id, message, &error), true, "bob accepted %@: %@", SOSMessageCopyDescription(message), error); CFReleaseNull(error); CFReleaseNull(message); #endif #if 1 bool alice = true; int max_loops = 50; while (max_loops-- && NULL != (message = dequeueMessage())) { if (alice) { ok(SOSCircleHandlePeerMessage(aliceCircle, alice_full_peer_info, aliceDsf, enqueueMessage, bob_peer_id, message, &error), "alice accepted %@: %@", desc = SOSMessageCopyDescription(message), error); } else { ok(SOSCircleHandlePeerMessage(bobCircle, bob_full_peer_info, bobDsf, enqueueMessage, alice_peer_id, message, &error), "bob accepted %@: %@", desc = SOSMessageCopyDescription(message), error); } alice = !alice; CFRelease(message); CFReleaseNull(desc); } #endif CFReleaseNull(aliceCircle); CFReleaseNull(bobCircle); CFReleaseNull(alice_peer_info); CFReleaseNull(bob_peer_info); CFReleaseNull(alice_key); CFReleaseNull(bob_key); aliceDsf->release(aliceDsf); bobDsf->release(bobDsf); }