mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-19 03:33:36 +01:00
[AltServer] Handles EnableUnsignedCodeExecutionRequest
Allows sideloaded apps to connect to AltServer and enable JIT execution.
This commit is contained in:
@@ -16,6 +16,7 @@ NS_SWIFT_NAME(DebugConnection)
|
|||||||
@property (nonatomic, copy, readonly) ALTDevice *device;
|
@property (nonatomic, copy, readonly) ALTDevice *device;
|
||||||
|
|
||||||
- (void)enableUnsignedCodeExecutionForProcessWithName:(NSString *)processName completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler;
|
- (void)enableUnsignedCodeExecutionForProcessWithName:(NSString *)processName completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler;
|
||||||
|
- (void)enableUnsignedCodeExecutionForProcessWithID:(NSInteger)pid completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler;
|
||||||
|
|
||||||
- (void)disconnect;
|
- (void)disconnect;
|
||||||
|
|
||||||
|
|||||||
@@ -96,12 +96,36 @@ char *bin2hex(const unsigned char *bin, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)enableUnsignedCodeExecutionForProcessWithName:(NSString *)processName completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler
|
- (void)enableUnsignedCodeExecutionForProcessWithName:(NSString *)processName completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler
|
||||||
|
{
|
||||||
|
[self _enableUnsignedCodeExecutionForProcessWithName:processName pid:0 completionHandler:completionHandler];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)enableUnsignedCodeExecutionForProcessWithID:(NSInteger)pid completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler
|
||||||
|
{
|
||||||
|
[self _enableUnsignedCodeExecutionForProcessWithName:nil pid:(int32_t)pid completionHandler:completionHandler];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_enableUnsignedCodeExecutionForProcessWithName:(nullable NSString *)processName pid:(int32_t)pid completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler
|
||||||
{
|
{
|
||||||
dispatch_async(self.connectionQueue, ^{
|
dispatch_async(self.connectionQueue, ^{
|
||||||
NSString *localizedFailure = [NSString stringWithFormat:NSLocalizedString(@"JIT could not be enabled for %@.", comment: @""), processName];
|
NSString *name = processName ?: NSLocalizedString(@"this app", @"");
|
||||||
|
NSString *localizedFailure = [NSString stringWithFormat:NSLocalizedString(@"JIT could not be enabled for %@.", comment: @""), name];
|
||||||
|
|
||||||
NSString *encodedName = @(bin2hex((const unsigned char *)processName.UTF8String, (size_t)strlen(processName.UTF8String)));
|
NSString *attachCommand = nil;
|
||||||
NSString *attachCommand = [NSString stringWithFormat:@"vAttachName;%@", encodedName];
|
|
||||||
|
if (processName)
|
||||||
|
{
|
||||||
|
NSString *encodedName = @(bin2hex((const unsigned char *)processName.UTF8String, (size_t)strlen(processName.UTF8String)));
|
||||||
|
attachCommand = [NSString stringWithFormat:@"vAttachName;%@", encodedName];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Convert to Big-endian.
|
||||||
|
int32_t rawPID = CFSwapInt32HostToBig(pid);
|
||||||
|
|
||||||
|
NSString *encodedName = @(bin2hex((const unsigned char *)&rawPID, 4));
|
||||||
|
attachCommand = [NSString stringWithFormat:@"vAttach;%@", encodedName];
|
||||||
|
}
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
if (![self sendCommand:attachCommand arguments:nil error:&error])
|
if (![self sendCommand:attachCommand arguments:nil error:&error])
|
||||||
|
|||||||
@@ -143,6 +143,37 @@ struct ServerRequestHandler: RequestHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleEnableUnsignedCodeExecutionRequest(_ request: EnableUnsignedCodeExecutionRequest, for connection: Connection, completionHandler: @escaping (Result<EnableUnsignedCodeExecutionResponse, Error>) -> Void)
|
||||||
|
{
|
||||||
|
guard let device = ALTDeviceManager.shared.availableDevices.first(where: { $0.identifier == request.udid }) else { return completionHandler(.failure(ALTServerError(.deviceNotFound))) }
|
||||||
|
|
||||||
|
ALTDeviceManager.shared.prepare(device) { result in
|
||||||
|
switch result
|
||||||
|
{
|
||||||
|
case .failure(let error): completionHandler(.failure(error))
|
||||||
|
case .success:
|
||||||
|
ALTDeviceManager.shared.startDebugConnection(to: device) { (connection, error) in
|
||||||
|
guard let connection = connection else { return completionHandler(.failure(error!)) }
|
||||||
|
|
||||||
|
connection.enableUnsignedCodeExecutionForProcess(withID: request.processID) { (success, error) in
|
||||||
|
if let error = error, !success
|
||||||
|
{
|
||||||
|
print("Failed to enable unsigned code execution for process \(request.processID):", error)
|
||||||
|
completionHandler(.failure(ALTServerError(error)))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print("Enabled unsigned code execution for process:", request.processID)
|
||||||
|
|
||||||
|
let response = EnableUnsignedCodeExecutionResponse()
|
||||||
|
completionHandler(.success(response))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension RequestHandler
|
private extension RequestHandler
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ public protocol RequestHandler
|
|||||||
completionHandler: @escaping (Result<RemoveProvisioningProfilesResponse, Error>) -> Void)
|
completionHandler: @escaping (Result<RemoveProvisioningProfilesResponse, Error>) -> Void)
|
||||||
|
|
||||||
func handleRemoveAppRequest(_ request: RemoveAppRequest, for connection: Connection, completionHandler: @escaping (Result<RemoveAppResponse, Error>) -> Void)
|
func handleRemoveAppRequest(_ request: RemoveAppRequest, for connection: Connection, completionHandler: @escaping (Result<RemoveAppResponse, Error>) -> Void)
|
||||||
|
|
||||||
|
func handleEnableUnsignedCodeExecutionRequest(_ request: EnableUnsignedCodeExecutionRequest, for connection: Connection, completionHandler: @escaping (Result<EnableUnsignedCodeExecutionResponse, Error>) -> Void)
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol ConnectionHandler: AnyObject
|
public protocol ConnectionHandler: AnyObject
|
||||||
@@ -152,6 +154,11 @@ private extension ConnectionManager
|
|||||||
finish(result)
|
finish(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case .success(.enableUnsignedCodeExecution(let request)):
|
||||||
|
self.requestHandler.handleEnableUnsignedCodeExecutionRequest(request, for: connection) { (result) in
|
||||||
|
finish(result)
|
||||||
|
}
|
||||||
|
|
||||||
case .success(.unknown):
|
case .success(.unknown):
|
||||||
finish(Result<ErrorResponse, Error>.failure(ALTServerError(.unknownRequest)))
|
finish(Result<ErrorResponse, Error>.failure(ALTServerError(.unknownRequest)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public enum ServerRequest: Decodable
|
|||||||
case installProvisioningProfiles(InstallProvisioningProfilesRequest)
|
case installProvisioningProfiles(InstallProvisioningProfilesRequest)
|
||||||
case removeProvisioningProfiles(RemoveProvisioningProfilesRequest)
|
case removeProvisioningProfiles(RemoveProvisioningProfilesRequest)
|
||||||
case removeApp(RemoveAppRequest)
|
case removeApp(RemoveAppRequest)
|
||||||
|
case enableUnsignedCodeExecution(EnableUnsignedCodeExecutionRequest)
|
||||||
case unknown(identifier: String, version: Int)
|
case unknown(identifier: String, version: Int)
|
||||||
|
|
||||||
var identifier: String {
|
var identifier: String {
|
||||||
@@ -36,6 +37,7 @@ public enum ServerRequest: Decodable
|
|||||||
case .installProvisioningProfiles(let request): return request.identifier
|
case .installProvisioningProfiles(let request): return request.identifier
|
||||||
case .removeProvisioningProfiles(let request): return request.identifier
|
case .removeProvisioningProfiles(let request): return request.identifier
|
||||||
case .removeApp(let request): return request.identifier
|
case .removeApp(let request): return request.identifier
|
||||||
|
case .enableUnsignedCodeExecution(let request): return request.identifier
|
||||||
case .unknown(let identifier, _): return identifier
|
case .unknown(let identifier, _): return identifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,6 +51,7 @@ public enum ServerRequest: Decodable
|
|||||||
case .installProvisioningProfiles(let request): return request.version
|
case .installProvisioningProfiles(let request): return request.version
|
||||||
case .removeProvisioningProfiles(let request): return request.version
|
case .removeProvisioningProfiles(let request): return request.version
|
||||||
case .removeApp(let request): return request.version
|
case .removeApp(let request): return request.version
|
||||||
|
case .enableUnsignedCodeExecution(let request): return request.version
|
||||||
case .unknown(_, let version): return version
|
case .unknown(_, let version): return version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,6 +95,10 @@ public enum ServerRequest: Decodable
|
|||||||
let request = try RemoveAppRequest(from: decoder)
|
let request = try RemoveAppRequest(from: decoder)
|
||||||
self = .removeApp(request)
|
self = .removeApp(request)
|
||||||
|
|
||||||
|
case "EnableUnsignedCodeExecutionRequest":
|
||||||
|
let request = try EnableUnsignedCodeExecutionRequest(from: decoder)
|
||||||
|
self = .enableUnsignedCodeExecution(request)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
self = .unknown(identifier: identifier, version: version)
|
self = .unknown(identifier: identifier, version: version)
|
||||||
}
|
}
|
||||||
@@ -105,6 +112,7 @@ public enum ServerResponse: Decodable
|
|||||||
case installProvisioningProfiles(InstallProvisioningProfilesResponse)
|
case installProvisioningProfiles(InstallProvisioningProfilesResponse)
|
||||||
case removeProvisioningProfiles(RemoveProvisioningProfilesResponse)
|
case removeProvisioningProfiles(RemoveProvisioningProfilesResponse)
|
||||||
case removeApp(RemoveAppResponse)
|
case removeApp(RemoveAppResponse)
|
||||||
|
case enableUnsignedCodeExecution(EnableUnsignedCodeExecutionResponse)
|
||||||
case error(ErrorResponse)
|
case error(ErrorResponse)
|
||||||
case unknown(identifier: String, version: Int)
|
case unknown(identifier: String, version: Int)
|
||||||
|
|
||||||
@@ -116,6 +124,7 @@ public enum ServerResponse: Decodable
|
|||||||
case .installProvisioningProfiles(let response): return response.identifier
|
case .installProvisioningProfiles(let response): return response.identifier
|
||||||
case .removeProvisioningProfiles(let response): return response.identifier
|
case .removeProvisioningProfiles(let response): return response.identifier
|
||||||
case .removeApp(let response): return response.identifier
|
case .removeApp(let response): return response.identifier
|
||||||
|
case .enableUnsignedCodeExecution(let response): return response.identifier
|
||||||
case .error(let response): return response.identifier
|
case .error(let response): return response.identifier
|
||||||
case .unknown(let identifier, _): return identifier
|
case .unknown(let identifier, _): return identifier
|
||||||
}
|
}
|
||||||
@@ -129,6 +138,7 @@ public enum ServerResponse: Decodable
|
|||||||
case .installProvisioningProfiles(let response): return response.version
|
case .installProvisioningProfiles(let response): return response.version
|
||||||
case .removeProvisioningProfiles(let response): return response.version
|
case .removeProvisioningProfiles(let response): return response.version
|
||||||
case .removeApp(let response): return response.version
|
case .removeApp(let response): return response.version
|
||||||
|
case .enableUnsignedCodeExecution(let response): return response.version
|
||||||
case .error(let response): return response.version
|
case .error(let response): return response.version
|
||||||
case .unknown(_, let version): return version
|
case .unknown(_, let version): return version
|
||||||
}
|
}
|
||||||
@@ -169,6 +179,10 @@ public enum ServerResponse: Decodable
|
|||||||
let response = try RemoveAppResponse(from: decoder)
|
let response = try RemoveAppResponse(from: decoder)
|
||||||
self = .removeApp(response)
|
self = .removeApp(response)
|
||||||
|
|
||||||
|
case "EnableUnsignedCodeExecutionResponse":
|
||||||
|
let response = try EnableUnsignedCodeExecutionResponse(from: decoder)
|
||||||
|
self = .enableUnsignedCodeExecution(response)
|
||||||
|
|
||||||
case "ErrorResponse":
|
case "ErrorResponse":
|
||||||
let response = try ErrorResponse(from: decoder)
|
let response = try ErrorResponse(from: decoder)
|
||||||
self = .error(response)
|
self = .error(response)
|
||||||
@@ -424,3 +438,28 @@ public struct RemoveAppResponse: ServerMessageProtocol
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct EnableUnsignedCodeExecutionRequest: ServerMessageProtocol
|
||||||
|
{
|
||||||
|
public var version = 1
|
||||||
|
public var identifier = "EnableUnsignedCodeExecutionRequest"
|
||||||
|
|
||||||
|
public var udid: String
|
||||||
|
public var processID: Int
|
||||||
|
|
||||||
|
public init(udid: String, processID: Int)
|
||||||
|
{
|
||||||
|
self.udid = udid
|
||||||
|
self.processID = processID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct EnableUnsignedCodeExecutionResponse: ServerMessageProtocol
|
||||||
|
{
|
||||||
|
public var version = 1
|
||||||
|
public var identifier = "EnableUnsignedCodeExecutionResponse"
|
||||||
|
|
||||||
|
public init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user