main.m
1 #import <Foundation/Foundation.h> 2 #import <Foundation/NSXPCConnection_Private.h> 3 #import <unistd.h> 4 #import <xpc/private.h> 5 #import <sandbox.h> 6 7 #import <Security/SecEntitlements.h> 8 #import <utilities/debugging.h> 9 #import <utilities/SecFileLocations.h> 10 11 #import "KeychainStasher.h" 12 13 NSString* const KeychainStasherMachServiceName = @"com.apple.security.KeychainStasher"; 14 15 @interface ServiceDelegate : NSObject <NSXPCListenerDelegate> 16 @end 17 18 @implementation ServiceDelegate 19 20 - (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection { 21 // We should encounter no more than 1 transaction per boot in normal conditions, so get out of everyone's way ASAP 22 xpc_transaction_exit_clean(); 23 24 NSNumber* value = [newConnection valueForEntitlement:kSecEntitlementPrivateStashService]; 25 if (value == nil || ![value boolValue]) { 26 secerror("KeychainStasher: client not entitled, rejecting connection"); 27 [newConnection invalidate]; 28 return NO; 29 } 30 31 newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(KeychainStasherProtocol)]; 32 newConnection.exportedObject = [KeychainStasher new]; 33 [newConnection resume]; 34 return YES; 35 } 36 37 @end 38 39 int main(int argc, const char *argv[]) 40 { 41 if (geteuid() == 0) { 42 secerror("KeychainStasher invoked as root, do not want."); 43 return 1; 44 } else { 45 secnotice("KeychainStasher", "Invoked with uid %d", geteuid()); 46 } 47 48 NSString* analyticsdir = [[(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(nil) URLByAppendingPathComponent:@"Analytics/"] path]; 49 if (analyticsdir) { 50 const char* sandbox_parameters[] = {"ANALYTICSDIR", analyticsdir.UTF8String, NULL}; 51 char* sandbox_error = NULL; 52 if (0 != sandbox_init_with_parameters("com.apple.security.KeychainStasher", SANDBOX_NAMED, sandbox_parameters, &sandbox_error)) { 53 secerror("unable to enter sandbox with parameter: %s", sandbox_error); 54 sandbox_free_error(sandbox_error); 55 abort(); 56 } 57 } else { // If this fails somehow we will go ahead without analytics 58 char* sandbox_error = NULL; 59 if (0 != sandbox_init("com.apple.security.KeychainStasher", SANDBOX_NAMED, &sandbox_error)) { 60 secerror("unable to enter sandbox: %s", sandbox_error); 61 sandbox_free_error(sandbox_error); 62 abort(); 63 } 64 } 65 66 ServiceDelegate *delegate = [ServiceDelegate new]; 67 NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:KeychainStasherMachServiceName]; 68 listener.delegate = delegate; 69 [listener resume]; 70 [[NSRunLoop currentRunLoop] run]; 71 return 0; 72 }