2015-11-12 72 views
2

作爲我們移動設備管理功能的一部分,我們爲客戶提供私人appstore。管理員可以將ipa文件上傳到我們的服務器,我們將允許受管設備直接安裝這些企業應用程序。iOS - 爲私人應用商店驗證企業配置文件

當管理員上傳ipa時,我們要做一些驗證,如果ipa不符合要求,我們會立即拒絕。具體如下:

  1. 如果ipa是由企業證書(比如appstore證書)以外的證書籤名的,我們要拒絕它;
  2. 如果ipa由已過期的證書籤名,我們希望拒絕它;
  3. 如果ipa由已被吊銷的證書籤署,我們想要拒絕它。

我有以下問題:

  1. 對於要求#1,我已經注意到,企業必須建立在IPA文件embedded.mobileprovision,但AppStore的建立沒有文件。是否足以檢查該文件的存在以確定上傳的ipa是否是企業ipa,還是有更準確的方法來識別非企業ipa?
  2. 對於需求#2,它看起來像embedded.mobileprovision中有一個字段ExpirationDate,我可以檢查它的值來確定到期日期?
  3. 據我所知,上面#1和#2是可能的,但#3將無法驗證,直到用戶實際嘗試安裝ipa。也就是說,當管理員上傳ipa時,我無法捕捉到錯誤,但是我會允許這樣做,並且用戶將得到無法安裝該應用程序的錯誤。

在此先感謝。

+0

'[[一個NSBundle mainBundle] pathForResource:@ 「embedded.mobileprovision」 ofType:無]' http://stackoverflow.com/questions/17584426/check-if-app-is-ad-hocdevapp-商店集結在運行時。看到類似的問題。你可以得到一些想法 – aelam

+0

@aelam謝謝你的回覆。糾正我,如果我錯了,它看起來像線程是關於檢查應用程序代碼中的構建類型。在我的情況下,我們不擁有應用程序(因此我們無法訪問其源代碼),管理員上傳他們自己的應用程序 - 並且應用程序已簽名,因此我們無法將代碼注入到他們的應用程序中。我們掌握的僅僅是一個ipa文件,我想要一種直接從這個ipa獲取信息的方式。 – SeaJelly

回答

1

下面的代碼完成所需的任務。

Boolean foundMobileProvision = false; 
Pattern mobileProvisionPattern = Pattern.compile("embedded\\.mobileprovision$"); 

while ((entry = zipStream.getNextEntry()) != null) { 
    Matcher mobileProvisionMatcher = mobileProvisionPattern.matcher(entryName); 
    if (!entry.isDirectory()) { 
     if (mobileProvisionMatcher.find()) { 
      foundMobileProvision = true; 
      CMSSignedDataParser parser = new CMSSignedDataParser(new BcDigestCalculatorProvider(), zipStream); 
      InputStream plistContentStream = parser.getSignedContent().getContentStream(); 

      Map<String, Object> mobileProvisionAttributes = PlistParser.parsePlistToMap(plistContentStream); 

      plistContentStream.close(); 

      validateEnterpriseProvision(mobileProvisionAttributes); 
     } 
    } 
} 
zipStream.close(); 
if (!foundMobileProvision) { 
    throw new InvalidEnterpriseProvisionException("Uploaded app must have a valid enterprise provisioning profile"); 
} 

private void validateEnterpriseProvision(Map<String, Object> mobileProvisionAttributes) { 
    Boolean provisionAllDevices = (Boolean) mobileProvisionAttributes.get(IOS_MOBILE_PROVISION_ALL_DEVICES); 

    if (provisionAllDevices == null || !provisionAllDevices) { 
     throw new InvalidEnterpriseProvisionException("Uploaded app must have a valid enterprise provisioning profile"); 
    } 

    Date expirationDate = (Date) mobileProvisionAttributes.get(IOS_MOBILE_PROVISION_EXPIRATION_DATE); 
    if (new Date().after(expirationDate)) { 
     throw new EnterpriseProvisionExpiredException("Profile expired"); 
    } 
} 
+0

你能接受你的答案嗎? –

+0

@RhythmicFistman只是:) – SeaJelly

0

在你的ipa文件中有一個embedded.mobileprovision。

  1. 將它解壓縮,有一個有效載荷/ appName.app/
  2. 找出embedded.mobileprovision

試圖尋找到embedded.mobileprovision

這是一個二進制的plist(是的plist一個特殊的XML格式,但仍然是XML)。我可以用atom和vim查看它。你會注意到有不可讀的前綴和後綴,忽略它們。 進入中心部分。您可以看到許多節點,例如TeamIdentifier,AppIDName,ProvisionedDevices。它有很多工作人員。

按照您的要求,我發現了一些可能需要 碼https://github.com/0xc010d/mobileprovision-read/blob/master/main.m

它檢查mobileprovision的一些關鍵節點。少於4?

if ([option isEqualToString:@"type"]) { 
    if ([plist valueForKeyPath:@"ProvisionedDevices"]){ 
     if ([[plist valueForKeyPath:@"Entitlements.get-task-allow"] boolValue]) { 
      printf("debug\n"); 
     } 
     else { 
      printf("ad-hoc\n"); 
     } 
    } 
    else if ([[plist valueForKeyPath:@"ProvisionsAllDevices"] boolValue]) { 
      printf("enterprise\n"); 
    } 
    else { 
      printf("appstore\n"); 
    } 
} 

關於解析器

你可以寫一個命令行分析器工具,或者你可以在google之一。 步驟不會很難

  1. 修剪後綴,前綴
  2. 取一些節點的值一樣ProvisionedDevicesProvisionsAllDevices
  3. 如果ProvisionsAllDevicestrue。接受。