Подтвердить что ты не робот

Как определить, что профиль обеспечения предназначен для разработки или распространения, программно

Я хотел бы определить, является ли данный профиль обеспечения профилем разработки или профилем распространения (adhoc или store store). Мне нужно делать это чисто программно.

Я уже понимаю, как определить adhoc vs appstore. И меня особенно интересует dev и дистрибутив.

Я исследовал plists, внутренние для каждого типа профиля, и не могу найти различимую разницу (через security cms -D -i #{@profilePath}). Я также посмотрел на openssl api и использую это для некоторых манипуляций с сертификатами.

Это для пользовательской системы автоматической сборки xcode. В рамках проверки правильной сборки я должен убедиться, что указанный профиль не предназначен для разработки.

Возможно ли это? Если да, то как я могу программно различать два?

Заранее благодарим за любые идеи!

4b9b3361

Ответ 1

Это было то, что я занимался в одной из своих собственных систем построения для той же цели... позвольте вернуться в прошлое к 1-му дню "Программы для разработчиков iPhone". Если бы вы были вокруг сообщества в то время, вы можете помнить, что инструментальная цепочка была... мы будем говорить менее дружелюбно, чем сегодня.

Если вы хотите создать для AppStore или для сборки AdHoc, вам нужно было сделать этот любопытный файл entitlements.plist, а затем вставить фрагмент XML в тело этого файла. Затем вы запустили сборку, и в то время появилось волшебство, и явное присутствие этого файла делало работу по сборке, позволяло вам вручную создавать ваш IPA и вести бизнес как обычно. Теперь, когда мы на несколько лет старше и, надеюсь, немного мудрее, чем в те ранние дни SDK, мы пришли к пониманию того, что волшебный XML-блок не был на самом деле настолько волшебным вообще - "получить задание-разрешить", key - это параметр, указывающий, должен ли двоичный файл подключать к двоичному файлу другие процессы (например, отладчик). При подписании приложений с использованием профиля Provisioning Development этот ключ будет установлен на "true" (и, таким образом, LLDB может подключаться и взаимодействовать с вашим приложением)... и, естественно, при подписании приложений с использованием профиля распределения распределения этот ключ будет установлен на "false".

Apple предоставила некоторые обновления в Tech Note TN2250 о чтении XML (а также дополнительных прав) из профилей Provisioning:

security cms -D -i/path/to/the.app/embedded.mobileprovision

Это вернет XML в профиле Provisioning - оттуда вы можете проанализировать пару значений ключа для "get-task-allow" и использовать это значение, чтобы определить, является ли профиль Provisioning Profile или Distribution.

Я абсолютно согласен с тем, что было бы неплохо иметь инструмент, который бы прямо сказал нам, что нам не нужно обнюхать профиль для подсказок, но в то же время, по крайней мере, у нас есть очень надежная, хотя обходной путь, чтобы сделать это различие перед запуском и создания сборки, которую мы не можем использовать.

Удачи и дайте мне знать, если вам нужно больше разъяснений или у вас есть другие вопросы.

Ответ 2

Я построил более сжатую и эффективную версию кода Toom:

Я буду содержать фрагменты кода, подобные этому в сущности, вы можете найти более современную версию здесь: https://gist.github.com/steipete/7668246

static BOOL PSPDFIsDevelopmentBuild(void) {
#if TARGET_IPHONE_SIMULATOR
return YES;
#else
static BOOL isDevelopment = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // There is no provisioning profile in AppStore Apps.
    NSData *data = [NSData dataWithContentsOfFile:[NSBundle.mainBundle pathForResource:@"embedded" ofType:@"mobileprovision"]];
    if (data) {
        const char *bytes = [data bytes];
        NSMutableString *profile = [[NSMutableString alloc] initWithCapacity:data.length];
        for (NSUInteger i = 0; i < data.length; i++) {
            [profile appendFormat:@"%c", bytes[i]];
        }
        // Look for debug value, if detected we're a development build.
        NSString *cleared = [[profile componentsSeparatedByCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet] componentsJoinedByString:@""];
        isDevelopment = [cleared rangeOfString:@"<key>get-task-allow</key><true/>"].length > 0;
    }
});
return isDevelopment;
#endif
}

Ответ 3

На основе большого ответа Bryan Musial я написал код, который позволяет вам проверять "get-task-allow" непосредственно из приложения во время выполнения. В моем случае я использую это логическое значение только для входа в отладочные приложения:

+ (BOOL)isDevelopmentApp
{
    // Special case of simulator
    if (isSimulator)
    {
        return YES;
    }

    // There is no provisioning profile in AppStore Apps
    NSString *profilePath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];

    // Check provisioning profile existence
    if (profilePath)
    {
        // Get hex representation
        NSData *profileData = [NSData dataWithContentsOfFile:profilePath];
        NSString *profileString = [NSString stringWithFormat:@"%@", profileData];

        // Remove brackets at beginning and end
        profileString = [profileString stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:@""];
        profileString = [profileString stringByReplacingCharactersInRange:NSMakeRange(profileString.length - 1, 1) withString:@""];

        // Remove spaces
        profileString = [profileString stringByReplacingOccurrencesOfString:@" " withString:@""];

        // Convert hex values to readable characters
        NSMutableString *profileText = [NSMutableString new];
        for (int i = 0; i < profileString.length; i += 2)
        {
            NSString *hexChar = [profileString substringWithRange:NSMakeRange(i, 2)];
            int value = 0;
            sscanf([hexChar cStringUsingEncoding:NSASCIIStringEncoding], "%x", &value);
            [profileText appendFormat:@"%c", (char)value];
        }

        // Remove whitespaces and new lines characters
        NSArray *profileWords = [profileText componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        NSString *profileClearText = [profileWords componentsJoinedByString:@""];

        // Look for debug value
        NSRange debugRange = [profileClearText rangeOfString:@"<key>get-task-allow</key><true/>"];
        if (debugRange.location != NSNotFound)
        {
            return YES;
        }
    }

    // Return NO by default to avoid security leaks
    return NO;
}

Ответ 4

Вот версия для Swift 3, основанная на ответе @steipete:

static func isDevelopmentProvisioningProfile() -> Bool {
#if IOS_SIMULATOR
    return true
#else
    // there will be no provisioning profile in AppStore Apps
    guard let fileName = Bundle.main.path(forResource: "embedded", ofType: "mobileprovision") else {
        return false
    }

    let fileURL = URL(fileURLWithPath: fileName)
    // the documentation says this file is in UTF-8, but that failed
    // on my machine. ASCII encoding worked ¯\_(ツ)_/¯
    guard let data = try? String(contentsOf: fileURL, encoding: .ascii) else {
        return false
    }

    let cleared: String = data.components(separatedBy: .whitespacesAndNewlines).joined()
    return cleared.contains("<key>get-task-allow</key><true/>")
#endif
}