mirror of
https://github.com/sparkle-project/Sparkle.git
synced 2025-11-01 15:34:38 +00:00
* For the Installer and Downloader XPC Services, if these executables are code signed with an Apple issued Team ID, then the connecting client must also be code signed with a matching Team ID. * For the Downloader XPC Service, the request URL must be http/https * For Autoupdate, if stage 1 of installation hasn't been completed yet and this executable is code signed with an Apple issued Team ID, then the connecting client must also be code signed with a matching Team ID. As before, multiple simultaneous connections are still disallowed. * For Autoupdate, if it's not signed with Apple issued certificate, when installing package updates the bundle being updated must be itself and owned by root on disk (as one expects from a PKG installation) * The authorization prompt message in the Installer Service is more computed inside the service so the client can't pass a completely arbitrary message * Add extra nullable checking of parameters coming from XPC endpoints * Add more thread-safe synchronization for Autoupdate installer * Add logs for more failure points
73 lines
3.0 KiB
Objective-C
73 lines
3.0 KiB
Objective-C
//
|
|
// main.m
|
|
// InstallerLauncher
|
|
//
|
|
// Created by Mayur Pawashe on 4/1/16.
|
|
// Copyright © 2016 Sparkle Project. All rights reserved.
|
|
//
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import "SUInstallerLauncher.h"
|
|
#import "SULog.h"
|
|
#import "SUCodeSigningVerifier.h"
|
|
|
|
@interface ServiceDelegate : NSObject <NSXPCListenerDelegate>
|
|
@end
|
|
|
|
@implementation ServiceDelegate
|
|
|
|
- (BOOL)listener:(NSXPCListener *)__unused listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
|
|
// This method is where the NSXPCListener configures, accepts, and resumes a new incoming NSXPCConnection.
|
|
|
|
// Validate connection of clients to avoid any client from using the service.
|
|
// This is a policy, not a security critical enforcement.
|
|
{
|
|
NSError *validationError = nil;
|
|
SUValidateConnectionStatus validationStatus = [SUCodeSigningVerifier validateConnection:newConnection options: SUValidateConnectionOptionDefault error:&validationError];
|
|
switch (validationStatus) {
|
|
case SUValidateConnectionStatusSetCodeSigningRequirementSuccess:
|
|
break;
|
|
case SUValidateConnectionStatusSetNoRequirementSuccess:
|
|
break;
|
|
case SUValidateConnectionStatusAPIFailure:
|
|
case SUValidateConnectionStatusCodeSigningRequirementFailure:
|
|
case SUValidateConectionNoSupportedValidationMethodFailure:
|
|
SULog(SULogLevelError, @"Error: Installer XPC Service is rejecting new connection due to failing validation of XPC connection with status %lu and error: %@", validationStatus, validationError.localizedDescription);
|
|
|
|
[newConnection invalidate];
|
|
|
|
return NO;
|
|
}
|
|
}
|
|
|
|
// Configure the connection.
|
|
// First, set the interface that the exported object implements.
|
|
newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(SUInstallerLauncherProtocol)];
|
|
|
|
// Next, set the object that the connection exports. All messages sent on the connection to this service will be sent to the exported object to handle. The connection retains the exported object.
|
|
SUInstallerLauncher *exportedObject = [SUInstallerLauncher new];
|
|
newConnection.exportedObject = exportedObject;
|
|
|
|
// Resuming the connection allows the system to deliver more incoming messages.
|
|
[newConnection resume];
|
|
|
|
// Returning YES from this method tells the system that you have accepted this connection. If you want to reject the connection for some reason, call -invalidate on the connection and return NO.
|
|
return YES;
|
|
}
|
|
|
|
@end
|
|
|
|
int main(int __unused argc, const char * __unused argv[])
|
|
{
|
|
// Create the delegate for the service.
|
|
ServiceDelegate *delegate = [ServiceDelegate new];
|
|
|
|
// Set up the one NSXPCListener for this service. It will handle all incoming connections.
|
|
NSXPCListener *listener = [NSXPCListener serviceListener];
|
|
listener.delegate = delegate;
|
|
|
|
// Resuming the serviceListener starts this service. This method does not return.
|
|
[listener resume];
|
|
return 0;
|
|
}
|