]>
Commit | Line | Data |
---|---|---|
1 | // | |
2 | // SOSAccountCircles.c | |
3 | // sec | |
4 | // | |
5 | ||
6 | #include "SOSAccountPriv.h" | |
7 | #include <Security/SecureObjectSync/SOSPeerInfoCollections.h> | |
8 | #include <Security/SecureObjectSync/SOSTransport.h> | |
9 | #include <Security/SecureObjectSync/SOSTransportKeyParameterKVS.h> | |
10 | #include <Security/SecureObjectSync/SOSTransportCircleKVS.h> | |
11 | #include <Security/SecureObjectSync/SOSTransportMessageKVS.h> | |
12 | #include <Security/SecureObjectSync/SOSTransportMessageIDS.h> | |
13 | #include "SOSCloudKeychainClient.h" | |
14 | ||
15 | ||
16 | // | |
17 | // MARK: Circle management | |
18 | // | |
19 | ||
20 | SecKeyRef SOSAccountCopyPublicKeyForPeer(SOSAccountRef account, CFStringRef peer_id, CFErrorRef *error) { | |
21 | SecKeyRef publicKey = NULL; | |
22 | SOSPeerInfoRef peer = NULL; | |
23 | ||
24 | require_action_quiet(account->trusted_circle, fail, SOSErrorCreate(kSOSErrorNoCircle, error, NULL, CFSTR("No circle to get peer key from"))); | |
25 | ||
26 | peer = SOSCircleCopyPeerWithID(account->trusted_circle, peer_id, error); | |
27 | require_quiet(peer, fail); | |
28 | ||
29 | publicKey = SOSPeerInfoCopyPubKey(peer, error); | |
30 | ||
31 | fail: | |
32 | CFReleaseSafe(peer); | |
33 | return publicKey; | |
34 | } | |
35 | ||
36 | ||
37 | SOSCircleRef SOSAccountGetCircle(SOSAccountRef a, CFErrorRef *error) | |
38 | { | |
39 | CFTypeRef entry = a->trusted_circle; | |
40 | ||
41 | require_action_quiet(!isNull(entry), fail, | |
42 | SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Incompatible circle in KVS"), NULL, error)); | |
43 | ||
44 | require_action_quiet(entry, fail, | |
45 | SOSCreateError(kSOSErrorNoCircle, CFSTR("No circle found"), NULL, error)); | |
46 | ||
47 | ||
48 | return (SOSCircleRef) entry; | |
49 | ||
50 | fail: | |
51 | return NULL; | |
52 | } | |
53 | ||
54 | static bool SOSAccountInflateTransportsForCircle(SOSAccountRef account, CFStringRef circleName, CFErrorRef *error){ | |
55 | bool success = false; | |
56 | ||
57 | SOSTransportKeyParameterRef tKey = NULL; | |
58 | SOSTransportCircleRef tCircle = NULL; | |
59 | SOSTransportMessageRef tidsMessage = NULL; | |
60 | SOSTransportMessageRef tkvsMessage = NULL; | |
61 | ||
62 | tKey = (SOSTransportKeyParameterRef)SOSTransportKeyParameterKVSCreate(account, error); | |
63 | tCircle = (SOSTransportCircleRef)SOSTransportCircleKVSCreate(account, circleName, error); | |
64 | ||
65 | require_quiet(tKey, fail); | |
66 | require_quiet(tCircle, fail); | |
67 | ||
68 | tidsMessage = (SOSTransportMessageRef)SOSTransportMessageIDSCreate(account, circleName, error); | |
69 | require_quiet(tidsMessage, fail); | |
70 | ||
71 | CFRetainAssign(account->ids_message_transport, tidsMessage); | |
72 | ||
73 | tkvsMessage = (SOSTransportMessageRef)SOSTransportMessageKVSCreate(account, circleName, error); | |
74 | require_quiet(tkvsMessage, fail); | |
75 | ||
76 | CFRetainAssign(account->kvs_message_transport, tkvsMessage); | |
77 | ||
78 | CFRetainAssign(account->key_transport, (SOSTransportKeyParameterRef)tKey); | |
79 | CFRetainAssign(account->circle_transport, tCircle); | |
80 | ||
81 | ||
82 | success = true; | |
83 | fail: | |
84 | CFReleaseNull(tKey); | |
85 | CFReleaseNull(tCircle); | |
86 | CFReleaseNull(tidsMessage); | |
87 | CFReleaseNull(tkvsMessage); | |
88 | return success; | |
89 | } | |
90 | ||
91 | SOSCircleRef SOSAccountEnsureCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error) | |
92 | { | |
93 | CFErrorRef localError = NULL; | |
94 | ||
95 | if (a->trusted_circle == NULL) { | |
96 | a->trusted_circle = SOSCircleCreate(NULL, name, NULL); | |
97 | a->key_interests_need_updating = true; | |
98 | } | |
99 | ||
100 | ||
101 | SOSCircleRef circle = SOSAccountGetCircle(a, &localError); | |
102 | ||
103 | require_action_quiet(circle || !isSOSErrorCoded(localError, kSOSErrorIncompatibleCircle), fail, | |
104 | if (error) { *error = localError; localError = NULL; }); | |
105 | ||
106 | require_quiet(SOSAccountInflateTransportsForCircle(a, name, error), fail); | |
107 | ||
108 | fail: | |
109 | CFReleaseNull(localError); | |
110 | return circle; | |
111 | } | |
112 | ||
113 | ||
114 | bool SOSAccountUpdateCircleFromRemote(SOSAccountRef account, SOSCircleRef newCircle, CFErrorRef *error) | |
115 | { | |
116 | return SOSAccountHandleUpdateCircle(account, newCircle, false, error); | |
117 | } | |
118 | ||
119 | bool SOSAccountUpdateCircle(SOSAccountRef account, SOSCircleRef newCircle, CFErrorRef *error) | |
120 | { | |
121 | return SOSAccountHandleUpdateCircle(account, newCircle, true, error); | |
122 | } | |
123 | ||
124 | bool SOSAccountModifyCircle(SOSAccountRef account, | |
125 | CFErrorRef* error, | |
126 | bool (^action)(SOSCircleRef circle)) | |
127 | { | |
128 | bool success = false; | |
129 | ||
130 | SOSCircleRef circle = NULL; | |
131 | require_action_quiet(account->trusted_circle, fail, SOSErrorCreate(kSOSErrorNoCircle, error, NULL, CFSTR("No circle to get peer key from"))); | |
132 | ||
133 | circle = SOSCircleCopyCircle(kCFAllocatorDefault, account->trusted_circle, error); | |
134 | require_quiet(circle, fail); | |
135 | ||
136 | success = true; | |
137 | require_quiet(action(circle), fail); | |
138 | ||
139 | success = SOSAccountUpdateCircle(account, circle, error); | |
140 | ||
141 | fail: | |
142 | CFReleaseSafe(circle); | |
143 | return success; | |
144 | } | |
145 | ||
146 | CFSetRef SOSAccountCopyPeerSetMatching(SOSAccountRef account, bool (^action)(SOSPeerInfoRef peer)) { | |
147 | CFMutableSetRef result = CFSetCreateMutableForSOSPeerInfosByID(kCFAllocatorDefault); | |
148 | ||
149 | if (account->trusted_circle) { | |
150 | SOSCircleForEachPeer(account->trusted_circle, ^(SOSPeerInfoRef peer) { | |
151 | if (action(peer)) { | |
152 | CFSetAddValue(result, peer); | |
153 | } | |
154 | }); | |
155 | } | |
156 | ||
157 | return result; | |
158 | } |