mirror of
https://github.com/StikDebug/StikDebug.git
synced 2026-10-15 20:10:30 +00:00
177 lines
6 KiB
Objective-C
177 lines
6 KiB
Objective-C
//
|
|
// profiles.m
|
|
// StikDebug
|
|
//
|
|
// Created by s s on 2025/11/29.
|
|
//
|
|
#include "profiles.h"
|
|
@import Foundation;
|
|
@import Security;
|
|
|
|
NSError* makeError(int code, NSString* msg) {
|
|
return [NSError errorWithDomain:@"profiles" code:code userInfo:@{NSLocalizedDescriptionKey: msg}];
|
|
}
|
|
|
|
|
|
NSArray<NSData*>* fetchAppProfiles(IdeviceProviderHandle* provider, NSError** error) {
|
|
MisagentClientHandle* misagentHandle = 0;
|
|
IdeviceFfiError * err = misagent_connect(provider, &misagentHandle);
|
|
if (err) {
|
|
*error = makeError(err->code, @(err->message));
|
|
idevice_error_free(err);
|
|
return nil;
|
|
}
|
|
|
|
uint8_t** profileArr = 0;
|
|
size_t profileCount = 0;
|
|
size_t* profileLengthArr = 0;
|
|
err = misagent_copy_all(misagentHandle, &profileArr, &profileLengthArr, &profileCount);
|
|
|
|
if (err) {
|
|
*error = makeError((err)->code, @((err)->message));
|
|
misagent_client_free(misagentHandle);
|
|
idevice_error_free(err);
|
|
return nil;
|
|
}
|
|
|
|
NSMutableArray* ans = [NSMutableArray array];
|
|
for(int i = 0; i < profileCount; ++i) {
|
|
size_t len = profileLengthArr[i];
|
|
uint8_t* profile = profileArr[i];
|
|
NSData* profileData = [NSData dataWithBytes:profile length:len];
|
|
|
|
[ans addObject:profileData];
|
|
}
|
|
|
|
misagent_free_profiles(profileArr, profileLengthArr, profileCount);
|
|
misagent_client_free(misagentHandle);
|
|
|
|
return ans;
|
|
}
|
|
|
|
bool removeProfile(IdeviceProviderHandle* provider, NSString* uuid, NSError** error) {
|
|
MisagentClientHandle* misagentHandle = 0;
|
|
IdeviceFfiError * err = misagent_connect(provider, &misagentHandle);
|
|
if (err) {
|
|
*error = makeError(err->code, @(err->message));
|
|
idevice_error_free(err);
|
|
return false;
|
|
}
|
|
|
|
err = misagent_remove(misagentHandle, [uuid UTF8String]);
|
|
if (err) {
|
|
*error = makeError((err)->code, @((err)->message));
|
|
misagent_client_free(misagentHandle);
|
|
idevice_error_free(err);
|
|
return false;
|
|
}
|
|
|
|
misagent_client_free(misagentHandle);
|
|
return true;
|
|
}
|
|
|
|
bool addProfile(IdeviceProviderHandle* provider, NSData* profile, NSError** error) {
|
|
MisagentClientHandle* misagentHandle = 0;
|
|
IdeviceFfiError * err = misagent_connect(provider, &misagentHandle);
|
|
if (err) {
|
|
*error = makeError(err->code, @(err->message));
|
|
idevice_error_free(err);
|
|
return false;
|
|
}
|
|
|
|
err = misagent_install(misagentHandle, [profile bytes], [profile length]);
|
|
if (err) {
|
|
*error = makeError((err)->code, @((err)->message));
|
|
misagent_client_free(misagentHandle);
|
|
idevice_error_free(err);
|
|
return false;
|
|
}
|
|
|
|
misagent_client_free(misagentHandle);
|
|
return true;
|
|
}
|
|
|
|
typedef CFTypeRef CMSDecoderRef;
|
|
OSStatus CMSDecoderCreate(CMSDecoderRef * cmsDecoderOut);
|
|
OSStatus CMSDecoderUpdateMessage(CMSDecoderRef cmsDecoder, const void * msgBytes, size_t msgBytesLen);
|
|
OSStatus CMSDecoderFinalizeMessage(CMSDecoderRef cmsDecoder);
|
|
OSStatus CMSDecoderCopyContent(CMSDecoderRef cmsDecoder, CFDataRef * contentOut);
|
|
OSStatus CMSDecoderCopyAllCerts(CMSDecoderRef cmsDecoder, CFArrayRef * certsOut);
|
|
|
|
|
|
// Helper to convert OSStatus -> NSError
|
|
static NSError *NSErrorFromOSStatus(OSStatus status, NSString *message) {
|
|
if (status == errSecSuccess) return nil;
|
|
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: message ?: @"Security error",
|
|
@"OSStatus" : @(status) };
|
|
return [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:userInfo];
|
|
}
|
|
|
|
|
|
@implementation CMSDecoderHelper
|
|
|
|
+ (NSData*)decodeCMSData:(NSData *)cmsData
|
|
// outCerts:(NSArray<id> * _Nullable * _Nullable)outCerts
|
|
error:(NSError * _Nullable * _Nullable)error
|
|
{
|
|
if (!cmsData) {
|
|
if (error) *error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSURLErrorBadURL userInfo:@{NSLocalizedDescriptionKey: @"cmsData is nil"}];
|
|
return nil;
|
|
}
|
|
|
|
CMSDecoderRef decoder = NULL;
|
|
OSStatus status = CMSDecoderCreate(&decoder);
|
|
if (status != errSecSuccess || decoder == NULL) {
|
|
if (error) *error = NSErrorFromOSStatus(status, @"Failed to create CMS decoder");
|
|
return nil;
|
|
}
|
|
|
|
// Feed data to decoder
|
|
status = CMSDecoderUpdateMessage(decoder, cmsData.bytes, cmsData.length);
|
|
if (status != errSecSuccess) {
|
|
if (error) *error = NSErrorFromOSStatus(status, @"Failed to update CMS decoder with message bytes");
|
|
CFRelease(decoder);
|
|
return nil;
|
|
}
|
|
|
|
// Finalize (parse) the message
|
|
status = CMSDecoderFinalizeMessage(decoder);
|
|
if (status != errSecSuccess) {
|
|
if (error) *error = NSErrorFromOSStatus(status, @"Failed to finalize CMS message");
|
|
CFRelease(decoder);
|
|
return nil;
|
|
}
|
|
|
|
// Extract the content (the inner payload). This may be NULL if content is detached.
|
|
CFDataRef contentData = NULL;
|
|
status = CMSDecoderCopyContent(decoder, &contentData);
|
|
if (status != errSecSuccess && status != errSecItemNotFound) {
|
|
// errSecItemNotFound could mean no content (detached signature)
|
|
if (error) *error = NSErrorFromOSStatus(status, @"Failed to copy CMS content");
|
|
if (contentData) CFRelease(contentData);
|
|
CFRelease(decoder);
|
|
return nil;
|
|
}
|
|
|
|
// // Extract embedded certificates (if any)
|
|
// CFArrayRef certsArray = NULL;
|
|
// status = CMSDecoderCopyAllCerts(decoder, &certsArray);
|
|
// if (status == errSecSuccess && certsArray) {
|
|
// // certsArray contains SecCertificateRef items
|
|
// NSArray *certs = (__bridge_transfer NSArray *)certsArray;
|
|
// if (outCerts) *outCerts = certs;
|
|
// } else {
|
|
// // no certs or error
|
|
// if (status != errSecSuccess && status != errSecItemNotFound) {
|
|
// if (error) *error = NSErrorFromOSStatus(status, @"Failed to copy embedded certificates (if any)");
|
|
// CFRelease(decoder);
|
|
// return NO;
|
|
// }
|
|
// if (outCerts) *outCerts = @[]; // empty
|
|
// }
|
|
|
|
CFRelease(decoder);
|
|
return (__bridge NSData *)(contentData);
|
|
}
|
|
|
|
@end
|