2013-04-26 7 views
25

Chciałbym wykryć, czy dany profil informacyjny jest profilem programisty lub profilem dystrybucji (sklepu adhoc lub sklepu z aplikacjami). Muszę to zrobić czysto programowo.Jak wykryć, że profil zaopatrzeniowy służy do programowania lub dystrybucji, programowo

Już rozumiem, jak wykrywać adhoc vs appstore. Szczególnie interesuje mnie programista a dystrybucja.

Przeanalizowałem pliki wewnętrzne każdego typu profilu i nie mogłem znaleźć dostrzegalnej różnicy (przez security cms -D -i #{@profilePath}). Sprawdziłem także api openssl i używam tego do manipulowania certyfikatami.

To jest dla niestandardowego systemu automatycznego budowania xcode. W ramach sprawdzania poprawności przed kompilacją muszę się upewnić, że określony profil nie jest przeznaczony do programowania.

Czy to możliwe? Jeśli tak, jak mogę programowo rozróżnić te dwie opcje?

Z góry dziękujemy za wszelkie pomysły!

+0

To interesujące pytanie, +1. –

+0

Oczywiście ludzie z 'testflightapp.com' robią to dla plików .ipa, ale ja nawet nie wiem jak odróżnić adhoc/appstore, który robisz. Sądzę, że narzędzia wiersza poleceń XCode powinny zawierać "narzędzie do profilowania narzędzi do profilowania" i powinno to być zrobione za nas. To tylko bogate źródło dezorientacji użytkownika. Dzięki Apple. –

+0

Hi Warren P, fyi Wszystko, co robię, aby wykryć profil ad hoc vs appstore sprawdza obecność klucza "ProvisionedDevices" w pliku plist profilu, ponieważ profile aplikacji nie będą zawierały żadnych urządzeń. Może nie być głupim dowodem, ale system, w którym pracuję, służy temu celowi. Mam nadzieję, że to jest przydatne. –

Odpowiedz

18

To było coś, co rozwiązałem w jednym z moich własnych systemów kompilacji w tym samym celu ... cofnijmy się w czasie do Dnia 1 ówczesnego "Programu dla programistów iPhone'a". Jeśli byłeś wtedy w pobliżu społeczności, możesz pamiętać, że toolchain był ... powiedzmy mniej przyjazny ... niż jest dzisiaj.

Gdy chcesz zbudować dla AppStore lub dla buildów AdHoc, musisz zrobić ten ciekawy plik privileglements.plist, a następnie wkleić blob XML do treści tego pliku. Następnie uruchomiłeś kompilację i wtedy pojawiło się coś, co wydawało się być magią, a sama obecność tego pliku sprawiła, że ​​praca została wykonana, pozwoliła ci na ręczne skonstruowanie twojego IPA i kontynuowanie działalności tak jak zwykle. Teraz, gdy jesteśmy o kilka lat starsi i mam nadzieję, że jest nieco mądrzejszy niż w początkach SDK, zrozumieliśmy, że magiczny blob XML nie był w rzeczywistości tak magiczny - "get-task-allow" key to ustawienie wskazujące, czy plik binarny powinien zezwalać innym procesom (takim jak debugger) na dołączanie do pliku binarnego. Podczas podpisywania aplikacji przy użyciu profilu obsługi wersji programistycznych ten klucz zostanie ustawiony na "true" (i tym samym pozwoli LLDB na dołączanie i interakcję z aplikacją) ... i oczywiście podczas podpisywania aplikacji przy użyciu profilu udostępniania dystrybucji, ten klucz zostanie ustawiony na "fałsz".

Apple przedstawił kilka nowości w Tech Note TN2250 o czytanie XML (a co za tym idzie uprawnienia) z Provisioning Profile:

bezpieczeństwo cms -D -i /path/to/the.app/embedded. mobileprovision

ta zwróci XML w profilu Provisioning - stamtąd można analizować z pary wartość klucza dla „get-task-allow” i użyć tej wartości w celu określenia, czy profil jest Provisioning Development lub Dystrybucja .

Absolutnie zgadzam się, że byłoby miło mieć narzędzie, które powie nam, że bezpośrednio, więc nie musimy węszyć przez profil w poszukiwaniu wskazówek, ale jednocześnie mamy przynajmniej wysoce niezawodne, choć okrężną drogą do zrobienia tego rozróżnienia przed ucieczką i budowaniem, którego nie możemy użyć.

Powodzenia i daj mi znać, jeśli potrzebujesz więcej wyjaśnień lub masz inne pytania.

+0

Świetna odpowiedź, dokładnie to, czego szukałem, dziękuję za szczegółowe wyjaśnienie! –

+0

Serdecznie witamy! Klucz ProvisionedDevices jest nadal dobrym dodatkowym sprawdzianem; Nie używam tego w moim systemie, ale na pewno możesz. –

9

Na podstawie świetnej odpowiedzi Bryana Musiała napisałem kod, który pozwala sprawdzić "get-task-allow" bezpośrednio z aplikacji w czasie wykonywania.W moim przypadku używam tego logiczną tylko do logowania w aplikacji Debug:

+ (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; 
} 
+0

Dziękujemy za komentarz na temat buildów App Store bez profilu informacyjnego. Pomógł mi w debugowaniu tajemniczego wypadku! – phatmann

20

mam zbudować bardziej zwięzły i wydajną wersję kodu Toom za:

będę utrzymywać fragmenty kodu jak to w GIST może się okazać bardziej aktualnej wersji tutaj: 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 
} 
1

Oto wersja Swifta 3, na podstawie @ steipete na odpowiedź:

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 
} 
Powiązane problemy