]> git.saurik.com Git - apple/security.git/blob - Security/sec/SOSCircle/SecureObjectSync/SOSAccountCircles.c
Security-57031.10.10.tar.gz
[apple/security.git] / Security / sec / SOSCircle / SecureObjectSync / SOSAccountCircles.c
1 //
2 // SOSAccountCircles.c
3 // sec
4 //
5
6 #include "SOSAccountPriv.h"
7 #include <SecureObjectSync/SOSTransport.h>
8 #include <SecureObjectSync/SOSTransportKeyParameterKVS.h>
9 #include <SecureObjectSync/SOSTransportCircleKVS.h>
10 #include <SecureObjectSync/SOSTransportMessageKVS.h>
11
12 void SOSAccountForEachCircle(SOSAccountRef account, void (^process)(SOSCircleRef circle))
13 {
14 CFDictionaryForEach(account->circles, ^(const void* key, const void* value) {
15 assert(value);
16 process((SOSCircleRef)value);
17 });
18 }
19
20
21 void SOSAccountForEachKnownCircle(SOSAccountRef account,
22 void (^handle_incompatible)(CFStringRef name),
23 void (^handle_no_peer)(SOSCircleRef circle),
24 void (^handle_peer)(SOSCircleRef circle, SOSFullPeerInfoRef full_peer)) {
25 CFDictionaryForEach(account->circles, ^(const void *key, const void *value) {
26 if (isNull(value)) {
27 if (handle_incompatible)
28 handle_incompatible((CFStringRef)key);
29 } else {
30 SOSCircleRef circle = (SOSCircleRef) value;
31 CFRetainSafe(circle);
32 SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, SOSCircleGetName(circle), NULL);
33 if (!fpi) {
34 if (handle_no_peer)
35 handle_no_peer(circle);
36 } else {
37 CFRetainSafe(fpi);
38 if (handle_peer)
39 handle_peer(circle, fpi);
40 CFReleaseSafe(fpi);
41 }
42 CFReleaseSafe(circle);
43 }
44 });
45 }
46
47 //
48 // MARK: Circle management
49 //
50
51 int SOSAccountCountCircles(SOSAccountRef a) {
52 assert(a);
53 assert(a->circle_identities);
54 assert(a->circles);
55 return (int)CFDictionaryGetCount(a->circles);
56 }
57
58
59
60 SOSCircleRef SOSAccountFindCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error)
61 {
62 CFTypeRef entry = CFDictionaryGetValue(a->circles, name);
63
64 require_action_quiet(!isNull(entry), fail,
65 SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Incompatible circle in KVS"), NULL, error));
66
67 require_action_quiet(entry, fail,
68 SOSCreateError(kSOSErrorNoCircle, CFSTR("No circle found"), NULL, error));
69
70
71 return (SOSCircleRef) entry;
72
73 fail:
74 return NULL;
75 }
76
77
78 static bool SOSAccountInflateTransportsForCircle(SOSAccountRef account, CFStringRef circleName, CFErrorRef *error){
79 bool success = false;
80 SOSTransportKeyParameterRef tKey = NULL;
81 SOSTransportCircleRef tCircle = NULL;
82 SOSTransportMessageRef tMessage = NULL;
83
84 #if 0 // IDS_FUTURE
85 // Solve determining transport type without fullpeer
86 SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamed(account, circleName, error);
87 require_quiet(fpi, fail);
88 SOSPeerInfoRef myPeer = SOSFullPeerInfoGetPeerInfo(fpi);
89 require_quiet(myPeer, fail);
90 CFStringRef type = SOSPeerInfoGetTransportType(myPeer);
91 if(CFStringCompare(type, CFSTR("KVS"), 0) == kCFCompareEqualTo){
92 #endif
93 tKey = (SOSTransportKeyParameterRef)SOSTransportKeyParameterKVSCreate(account, error);
94 tCircle = (SOSTransportCircleRef)SOSTransportCircleKVSCreate(account, circleName, error);
95 tMessage = (SOSTransportMessageRef)SOSTransportMessageKVSCreate(account, circleName, error);
96 require_quiet(tKey, fail);
97 require_quiet(tCircle, fail);
98 require_quiet(tMessage, fail);
99
100 CFRetainAssign(account->key_transport, (SOSTransportKeyParameterRef)tKey);
101 CFDictionarySetValue(account->circle_transports, circleName, tCircle);
102 CFDictionarySetValue(account->message_transports, circleName, tMessage);
103 #if 0 // IDS_FUTURE
104 }
105 #endif
106 success = true;
107
108 fail:
109 CFReleaseNull(tKey);
110 CFReleaseNull(tCircle);
111 CFReleaseNull(tMessage);
112 return success;
113 }
114
115 SOSCircleRef SOSAccountEnsureCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error)
116 {
117 CFErrorRef localError = NULL;
118
119 SOSCircleRef circle = SOSAccountFindCircle(a, name, &localError);
120
121 require_action_quiet(circle || !isSOSErrorCoded(localError, kSOSErrorIncompatibleCircle), fail,
122 if (error) { *error = localError; localError = NULL; });
123
124 if(NULL == circle){
125 circle = SOSCircleCreate(NULL, name, NULL);
126 if (circle){
127 CFDictionaryAddValue(a->circles, name, circle);
128 CFRelease(circle);
129 circle = SOSAccountFindCircle(a, name, &localError);
130 }
131
132 SOSUpdateKeyInterest();
133 }
134
135 require_quiet(SOSAccountInflateTransportsForCircle(a, name, error), fail);
136
137 fail:
138 CFReleaseNull(localError);
139 return circle;
140 }
141
142
143 bool SOSAccountUpdateCircleFromRemote(SOSAccountRef account, SOSCircleRef newCircle, CFErrorRef *error)
144 {
145 return SOSAccountHandleUpdateCircle(account, newCircle, false, error);
146 }
147
148 bool SOSAccountUpdateCircle(SOSAccountRef account, SOSCircleRef newCircle, CFErrorRef *error)
149 {
150 return SOSAccountHandleUpdateCircle(account, newCircle, true, error);
151 }
152
153 bool SOSAccountModifyCircle(SOSAccountRef account,
154 CFStringRef circleName,
155 CFErrorRef* error,
156 bool (^action)(SOSCircleRef circle))
157 {
158 bool success = false;
159
160 SOSCircleRef circle = NULL;
161 SOSCircleRef accountCircle = SOSAccountFindCircle(account, circleName, error);
162 require_quiet(accountCircle, fail);
163
164 circle = SOSCircleCopyCircle(kCFAllocatorDefault, accountCircle, error);
165 require_quiet(circle, fail);
166
167 success = true;
168 require_quiet(action(circle), fail);
169
170 success = SOSAccountUpdateCircle(account, circle, error);
171
172 fail:
173 CFReleaseSafe(circle);
174 return success;
175 }
176