diff --git a/Source/MOLXPCConnection/MOLXPCConnection.h b/Source/MOLXPCConnection/MOLXPCConnection.h index 2f9178d..112e127 100644 --- a/Source/MOLXPCConnection/MOLXPCConnection.h +++ b/Source/MOLXPCConnection/MOLXPCConnection.h @@ -22,7 +22,8 @@ @code MOLXPCConnection *conn = [[MOLXPCConnection alloc] initServerWithName:@"MyServer"]; - conn.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyServerProtocol)]; + conn.privilegedExportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyPriamryServerProtocol)]; + conn.unprivilegedExportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MySecondaryServerProtocol)]; conn.exportedObject = myObject; [conn resume]; @endcode @@ -113,9 +114,20 @@ @property(readonly, nonatomic, nullable) id remoteObjectProxy; /** - The interface this object exports. (server) + The privileged interface this object exports. (server) */ -@property(retain, nullable) NSXPCInterface *exportedInterface; +@property(retain, nullable) NSXPCInterface *privilegedInterface; + +/** + The unprivileged interface this object exports. (server) + */ +@property(retain, nullable) NSXPCInterface *unprivilegedInterface; + +/** + Old interface property, please update to use privilegedExportedInterface and/or unprivilegedExportedInterface instead. +*/ +@property(retain, nullable) NSXPCInterface *exportedInterface __attribute__(( + deprecated("Use privilegedExportedInterface and / or unprivilegedExportedInterface instead."))); /** The object that responds to messages from the other end. (server) diff --git a/Source/MOLXPCConnection/MOLXPCConnection.m b/Source/MOLXPCConnection/MOLXPCConnection.m index de0da5a..3d14bd4 100644 --- a/Source/MOLXPCConnection/MOLXPCConnection.m +++ b/Source/MOLXPCConnection/MOLXPCConnection.m @@ -151,6 +151,22 @@ - (void)resume { } - (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)connection { + // Fail this connection if it's from an unprivileged user and we have been + // configured to only allow root/admins + NSXPCInterface *interface; + if ([connection effectiveUserIdentifier] == 0) { + interface = self.privilegedInterface; + } else { + interface = self.unprivilegedInterface; + } + + // TODO(any): Remove 1-2 releases after exportedInterface was marked deprecated. + if (!interface) { + interface = self.exportedInterface; + } + + if (!interface) return NO; + pid_t pid = connection.processIdentifier; MOLCodesignChecker *otherCS = [[MOLCodesignChecker alloc] initWithPID:pid]; if (![otherCS signingInformationMatches:[[MOLCodesignChecker alloc] initWithSelf]]) { @@ -170,7 +186,7 @@ - (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConne connection.invalidationHandler = connection.interruptionHandler = ^{ if (self.invalidationHandler) self.invalidationHandler(); }; - connection.exportedInterface = self.exportedInterface; + connection.exportedInterface = interface; connection.exportedObject = self.exportedObject; [connection resume]; diff --git a/Tests/MOLXPCConnectionTests.m b/Tests/MOLXPCConnectionTests.m index 6e109bc..5c2daa4 100644 --- a/Tests/MOLXPCConnectionTests.m +++ b/Tests/MOLXPCConnectionTests.m @@ -22,6 +22,9 @@ @interface MOLXPCConnectionTest : XCTestCase @end +@protocol DummyXPCProtocol +@end + @implementation MOLXPCConnectionTest - (void)testPlainInit { @@ -67,6 +70,7 @@ - (void)testConnectionRejection { NSXPCListener *listener = [NSXPCListener anonymousListener]; MOLXPCConnection *sutServer = [[MOLXPCConnection alloc] initServerWithListener:listener]; + sutServer.unprivilegedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(DummyXPCProtocol)]; [sutServer resume]; __block XCTestExpectation *exp1 = [self expectationWithDescription:@"Client Invalidated"]; @@ -87,6 +91,7 @@ - (void)testConnectionAcceptance { XCTestExpectation *exp1 = [self expectationWithDescription:@"Server Accepted"]; MOLXPCConnection *sutServer = [[MOLXPCConnection alloc] initServerWithListener:listener]; + sutServer.unprivilegedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(DummyXPCProtocol)]; sutServer.acceptedHandler = ^{ [exp1 fulfill]; }; @@ -105,6 +110,7 @@ - (void)testConnectionAcceptance { - (void)testConnectionInterruption { NSXPCListener *listener = [NSXPCListener anonymousListener]; MOLXPCConnection *sutServer = [[MOLXPCConnection alloc] initServerWithListener:listener]; + sutServer.unprivilegedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(DummyXPCProtocol)]; [sutServer resume]; __block XCTestExpectation *exp1 = [self expectationWithDescription:@"Client Invalidated"];