1 #import <Foundation/Foundation.h>
 
   2 #import <Foundation/NSXPCConnection_Private.h>
 
   3 #import <Security/SecEntitlements.h>
 
   4 #import <ipc/securityd_client.h>
 
   6 #import "SOSControlHelper.h"
 
   7 #import "SOSControlServer.h"
 
   9 @interface SOSControlServer : NSObject <NSXPCListenerDelegate>
 
  12 @interface SOSClient ()
 
  13 @property (strong) SOSAccount * account;
 
  14 - (instancetype)initSOSClientWithAccount:(SOSAccount *)account;
 
  15 - (bool)checkEntitlement:(NSString *)entitlement;
 
  18 @interface SOSClientRemote : SOSClient
 
  19 @property (weak) NSXPCConnection * connection;
 
  20 - (instancetype)initSOSConnectionWithConnection:(NSXPCConnection *)connection account:(SOSAccount *)account;
 
  23 @implementation SOSControlServer
 
  25 - (BOOL)listener:(__unused NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
 
  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);
 
  34     SOSAccount *account = (__bridge SOSAccount *)SOSKeychainAccountGetSharedAccount();
 
  36         secerror("sos: SOS have not launched yet, come later, pid: %d",
 
  37                 [newConnection processIdentifier]);
 
  41     SOSClientRemote *sosClient = [[SOSClientRemote alloc] initSOSConnectionWithConnection:newConnection account:account];
 
  43     newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(SOSControlProtocol)];
 
  44     _SOSControlSetupInterface(newConnection.exportedInterface);
 
  45     newConnection.exportedObject = sosClient;
 
  47     [newConnection resume];
 
  52 - (SOSClient *)internalSOSClient
 
  54     return [[SOSClient alloc] initSOSClientWithAccount:(__bridge SOSAccount *)SOSKeychainAccountGetSharedAccount()];
 
  59 @implementation SOSClient
 
  61 @synthesize account = _account;
 
  63 - (instancetype)initSOSClientWithAccount:(SOSAccount *)account
 
  65     if ((self = [super init])) {
 
  71 - (bool)checkEntitlement:(NSString *)entitlement
 
  76 - (void)userPublicKey:(void ((^))(BOOL trusted, NSData *spki, NSError *error))reply
 
  78     [self.account userPublicKey:reply];
 
  81 - (void)kvsPerformanceCounters:(void(^)(NSDictionary <NSString *, NSNumber *> *))reply
 
  83     [self.account kvsPerformanceCounters:reply];
 
  86 - (void)rateLimitingPerformanceCounters:(void(^)(NSDictionary <NSString *, NSString *> *))reply
 
  88     [self.account rateLimitingPerformanceCounters:reply];
 
  91 - (void)stashedCredentialPublicKey:(void(^)(NSData *, NSError *error))reply
 
  93     [self.account stashedCredentialPublicKey:reply];
 
  96 - (void)assertStashedAccountCredential:(void(^)(BOOL result, NSError *error))reply
 
  98     [self.account assertStashedAccountCredential:reply];
 
 101 - (void)validatedStashedAccountCredential:(void(^)(NSData *credential, NSError *error))complete
 
 103     [self.account validatedStashedAccountCredential:complete];
 
 106 - (void)stashAccountCredential:(NSData *)credential complete:(void(^)(bool success, NSError *error))complete
 
 108     [self.account stashAccountCredential:credential complete:complete];
 
 111 - (void)myPeerInfo:(void (^)(NSData *, NSError *))complete
 
 113     [self.account myPeerInfo:complete];
 
 116 - (void)circleHash:(void (^)(NSString *, NSError *))complete
 
 118     [self.account circleHash:complete];
 
 122 - (void)circleJoiningBlob:(NSData *)applicant complete:(void (^)(NSData *blob, NSError *))complete
 
 124     [self.account circleJoiningBlob:applicant complete:complete];
 
 127 - (void)joinCircleWithBlob:(NSData *)blob version:(PiggyBackProtocolVersion)version complete:(void (^)(bool success, NSError *))complete
 
 129     [self.account joinCircleWithBlob:blob version:version complete:complete];
 
 132 - (void)initialSyncCredentials:(uint32_t)flags complete:(void (^)(NSArray *, NSError *))complete
 
 134     if (![self checkEntitlement:(__bridge NSString *)kSecEntitlementKeychainInitialSync]) {
 
 135         complete(@[], [NSError errorWithDomain:(__bridge NSString *)kSOSErrorDomain code:kSOSEntitlementMissing userInfo:NULL]);
 
 139     [self.account initialSyncCredentials:flags complete:complete];
 
 142 - (void)importInitialSyncCredentials:(NSArray *)items complete:(void (^)(bool success, NSError *))complete
 
 144     if (![self checkEntitlement:(__bridge NSString *)kSecEntitlementKeychainInitialSync]) {
 
 145         complete(false, [NSError errorWithDomain:(__bridge NSString *)kSOSErrorDomain code:kSOSEntitlementMissing userInfo:NULL]);
 
 149     [self.account importInitialSyncCredentials:items complete:complete];
 
 152 - (void)triggerSync:(NSArray <NSString *> *)peers complete:(void(^)(bool success, NSError *))complete
 
 154     if (![self checkEntitlement:(__bridge NSString *)kSecEntitlementKeychainCloudCircle]) {
 
 155         complete(false, [NSError errorWithDomain:(__bridge NSString *)kSOSErrorDomain code:kSOSEntitlementMissing userInfo:NULL]);
 
 159     [self.account triggerSync:peers complete:complete];
 
 162 - (void)getWatchdogParameters:(void (^)(NSDictionary* parameters, NSError* error))complete
 
 164     [self.account getWatchdogParameters:complete];
 
 167 - (void)setWatchdogParmeters:(NSDictionary*)parameters complete:(void (^)(NSError* error))complete
 
 169     [self.account setWatchdogParmeters:parameters complete:complete];
 
 172 - (void) ghostBust:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool ghostBusted, NSError *error))complete {
 
 173     [self.account ghostBust:options complete:complete];
 
 176 - (void)ghostBustTriggerTimed:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool ghostBusted, NSError *error))complete {
 
 177     [self.account ghostBustTriggerTimed:options complete:complete];
 
 180 - (void) ghostBustPeriodic:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool busted, NSError *error))complete {
 
 181     [self.account ghostBustPeriodic:options complete:complete];
 
 184 - (void) ghostBustInfo: (void(^)(NSData *json, NSError *error))complete {
 
 185     [self.account ghostBustInfo:complete];
 
 188 - (void)triggerBackup:(NSArray<NSString *>* _Nullable)backupPeers complete:(void (^)(NSError *error))complete
 
 190     [self.account triggerBackup:backupPeers complete:complete];
 
 196 @implementation SOSClientRemote
 
 198 - (instancetype)initSOSConnectionWithConnection:(NSXPCConnection *)connection account:(SOSAccount *)account
 
 200     self = [super initSOSClientWithAccount:account];
 
 202         self.connection = connection;
 
 207 - (bool)checkEntitlement:(NSString *)entitlement
 
 209     NSXPCConnection *strongConnection = _connection;
 
 211     NSNumber *num = [strongConnection valueForEntitlement:entitlement];
 
 212     if (![num isKindOfClass:[NSNumber class]] || ![num boolValue]) {
 
 213         secerror("sos: Client pid: %d doesn't have entitlement: %@",
 
 214                  [strongConnection processIdentifier], entitlement);
 
 221 static SOSControlServer *sosServer;
 
 224 SOSControlServerInitialize(void)
 
 226     static dispatch_once_t once;
 
 227     static NSXPCListener *listener;
 
 229     dispatch_once(&once, ^{
 
 231             sosServer = [SOSControlServer new];
 
 233             listener = [[NSXPCListener alloc] initWithMachServiceName:@(kSecuritydSOSServiceName)];
 
 234             listener.delegate = sosServer;
 
 241 SOSControlServerInternalClient(void)
 
 243     SOSControlServerInitialize();
 
 244     return [sosServer internalSOSClient];