]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSAccountCircles.c
04afbfb8593a13cdb471255e36284d5684792fce
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSAccountCircles.c
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 }