SOSControlServer.m
1 #import <Foundation/Foundation.h> 2 #import <Foundation/NSXPCConnection_Private.h> 3 #import <Security/SecEntitlements.h> 4 #import <ipc/securityd_client.h> 5 #import "SOSAccount.h" 6 #import "SOSControlHelper.h" 7 #import "SOSControlServer.h" 8 9 @interface SOSControlServer : NSObject <NSXPCListenerDelegate> 10 @end 11 12 @interface SOSClient () 13 @property (strong) SOSAccount * account; 14 - (instancetype)initSOSClientWithAccount:(SOSAccount *)account; 15 - (bool)checkEntitlement:(NSString *)entitlement; 16 @end 17 18 @interface SOSClientRemote : SOSClient 19 @property (weak) NSXPCConnection * connection; 20 - (instancetype)initSOSConnectionWithConnection:(NSXPCConnection *)connection account:(SOSAccount *)account; 21 @end 22 23 @implementation SOSControlServer 24 25 - (BOOL)listener:(__unused NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection 26 { 27 NSNumber *num = [newConnection valueForEntitlement:(__bridge NSString *)kSecEntitlementKeychainCloudCircle]; 28 if (![num isKindOfClass:[NSNumber class]] || ![num boolValue]) { 29 secerror("sos: Client pid: %d doesn't have entitlement: %@", 30 [newConnection processIdentifier], kSecEntitlementKeychainCloudCircle); 31 return NO; 32 } 33 34 SOSAccount *account = (__bridge SOSAccount *)SOSKeychainAccountGetSharedAccount(); 35 if (account == nil) { 36 secerror("sos: SOS have not launched yet, come later, pid: %d", 37 [newConnection processIdentifier]); 38 return NO; 39 } 40 41 SOSClientRemote *sosClient = [[SOSClientRemote alloc] initSOSConnectionWithConnection:newConnection account:account]; 42 43 newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(SOSControlProtocol)]; 44 _SOSControlSetupInterface(newConnection.exportedInterface); 45 newConnection.exportedObject = sosClient; 46 47 [newConnection resume]; 48 49 return YES; 50 } 51 52 - (SOSClient *)internalSOSClient 53 { 54 return [[SOSClient alloc] initSOSClientWithAccount:(__bridge SOSAccount *)SOSKeychainAccountGetSharedAccount()]; 55 } 56 57 @end 58 59 @implementation SOSClient 60 61 @synthesize account = _account; 62 63 - (instancetype)initSOSClientWithAccount:(SOSAccount *)account 64 { 65 if ((self = [super init])) { 66 _account = account; 67 } 68 return self; 69 } 70 71 - (bool)checkEntitlement:(NSString *)entitlement 72 { 73 return true; 74 } 75 76 - (void)userPublicKey:(void ((^))(BOOL trusted, NSData *spki, NSError *error))reply 77 { 78 [self.account userPublicKey:reply]; 79 } 80 81 - (void)kvsPerformanceCounters:(void(^)(NSDictionary <NSString *, NSNumber *> *))reply 82 { 83 [self.account kvsPerformanceCounters:reply]; 84 } 85 86 - (void)rateLimitingPerformanceCounters:(void(^)(NSDictionary <NSString *, NSString *> *))reply 87 { 88 [self.account rateLimitingPerformanceCounters:reply]; 89 } 90 91 - (void)stashedCredentialPublicKey:(void(^)(NSData *, NSError *error))reply 92 { 93 [self.account stashedCredentialPublicKey:reply]; 94 } 95 96 - (void)assertStashedAccountCredential:(void(^)(BOOL result, NSError *error))reply 97 { 98 [self.account assertStashedAccountCredential:reply]; 99 } 100 101 - (void)validatedStashedAccountCredential:(void(^)(NSData *credential, NSError *error))complete 102 { 103 [self.account validatedStashedAccountCredential:complete]; 104 } 105 106 - (void)stashAccountCredential:(NSData *)credential complete:(void(^)(bool success, NSError *error))complete 107 { 108 [self.account stashAccountCredential:credential complete:complete]; 109 } 110 111 - (void)myPeerInfo:(void (^)(NSData *, NSError *))complete 112 { 113 [self.account myPeerInfo:complete]; 114 } 115 116 - (void)circleHash:(void (^)(NSString *, NSError *))complete 117 { 118 [self.account circleHash:complete]; 119 } 120 121 122 - (void)circleJoiningBlob:(NSData *)applicant complete:(void (^)(NSData *blob, NSError *))complete 123 { 124 [self.account circleJoiningBlob:applicant complete:complete]; 125 } 126 127 - (void)joinCircleWithBlob:(NSData *)blob version:(PiggyBackProtocolVersion)version complete:(void (^)(bool success, NSError *))complete 128 { 129 [self.account joinCircleWithBlob:blob version:version complete:complete]; 130 } 131 132 - (void)initialSyncCredentials:(uint32_t)flags complete:(void (^)(NSArray *, NSError *))complete 133 { 134 if (![self checkEntitlement:(__bridge NSString *)kSecEntitlementKeychainInitialSync]) { 135 complete(@[], [NSError errorWithDomain:(__bridge NSString *)kSOSErrorDomain code:kSOSEntitlementMissing userInfo:NULL]); 136 return; 137 } 138 139 [self.account initialSyncCredentials:flags complete:complete]; 140 } 141 142 - (void)importInitialSyncCredentials:(NSArray *)items complete:(void (^)(bool success, NSError *))complete 143 { 144 if (![self checkEntitlement:(__bridge NSString *)kSecEntitlementKeychainInitialSync]) { 145 complete(false, [NSError errorWithDomain:(__bridge NSString *)kSOSErrorDomain code:kSOSEntitlementMissing userInfo:NULL]); 146 return; 147 } 148 149 [self.account importInitialSyncCredentials:items complete:complete]; 150 } 151 152 - (void)rpcTriggerSync:(NSArray <NSString *> *)peers complete:(void(^)(bool success, NSError *))complete 153 { 154 [self.account rpcTriggerSync:peers complete:complete]; 155 } 156 157 - (void)getWatchdogParameters:(void (^)(NSDictionary* parameters, NSError* error))complete 158 { 159 [self.account getWatchdogParameters:complete]; 160 } 161 162 - (void)setWatchdogParmeters:(NSDictionary*)parameters complete:(void (^)(NSError* error))complete 163 { 164 [self.account setWatchdogParmeters:parameters complete:complete]; 165 } 166 167 - (void) ghostBust:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool ghostBusted, NSError *error))complete { 168 [self.account ghostBust:options complete:complete]; 169 } 170 171 - (void)ghostBustTriggerTimed:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool ghostBusted, NSError *error))complete { 172 [self.account ghostBustTriggerTimed:options complete:complete]; 173 } 174 175 - (void) ghostBustPeriodic:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool busted, NSError *error))complete { 176 [self.account ghostBustPeriodic:options complete:complete]; 177 } 178 179 - (void) ghostBustInfo: (void(^)(NSData *json, NSError *error))complete { 180 [self.account ghostBustInfo:complete]; 181 } 182 183 - (void)iCloudIdentityStatus: (void (^)(NSData *json, NSError *error))complete { 184 [self.account iCloudIdentityStatus: complete]; 185 } 186 187 - (void)rpcTriggerBackup:(NSArray<NSString *>* _Nullable)backupPeers complete:(void (^)(NSError *error))complete 188 { 189 [self.account rpcTriggerBackup:backupPeers complete:complete]; 190 } 191 192 - (void)rpcTriggerRingUpdate:(void (^)(NSError *))complete { 193 [self.account rpcTriggerRingUpdate:complete]; 194 } 195 196 - (void)iCloudIdentityStatus_internal:(void (^)(NSDictionary *, NSError *))complete { 197 [self.account iCloudIdentityStatus_internal:complete]; 198 } 199 200 - (void)removeV0Peers:(void (^)(bool, NSError *))reply { 201 [self.account removeV0Peers:reply]; 202 } 203 204 205 206 @end 207 208 @implementation SOSClientRemote 209 210 - (instancetype)initSOSConnectionWithConnection:(NSXPCConnection *)connection account:(SOSAccount *)account 211 { 212 if ((self = [super initSOSClientWithAccount:account])) { 213 self.connection = connection; 214 } 215 return self; 216 } 217 218 - (bool)checkEntitlement:(NSString *)entitlement 219 { 220 NSXPCConnection *strongConnection = _connection; 221 222 NSNumber *num = [strongConnection valueForEntitlement:entitlement]; 223 if (![num isKindOfClass:[NSNumber class]] || ![num boolValue]) { 224 secerror("sos: Client pid: %d doesn't have entitlement: %@", 225 [strongConnection processIdentifier], entitlement); 226 return false; 227 } 228 return true; 229 } 230 @end 231 232 static SOSControlServer *sosServer; 233 234 void 235 SOSControlServerInitialize(void) 236 { 237 static dispatch_once_t once; 238 static NSXPCListener *listener; 239 240 dispatch_once(&once, ^{ 241 @autoreleasepool { 242 sosServer = [SOSControlServer new]; 243 244 listener = [[NSXPCListener alloc] initWithMachServiceName:@(kSecuritydSOSServiceName)]; 245 listener.delegate = sosServer; 246 [listener resume]; 247 } 248 }); 249 } 250 251 SOSClient * 252 SOSControlServerInternalClient(void) 253 { 254 SOSControlServerInitialize(); 255 return [sosServer internalSOSClient]; 256 }