0 Replies
      Latest reply on Oct 16, 2015 2:37 AM by eskimo
      eskimo Apple Staff Apple Staff (10,255 points)

        This document describes how to debug code signing entitlement problems, with specific reference to the entitlements used by the Network Extension framework.

        The document was written for Xcode 7.0.

        You may also want to review Technote 2415 Entitlements Troubleshooting, which is a more official take on the subject.

        Check the Built Binary

        The first step in debugging code signing entitlement problems is to check the actual entitlements of the binary.  Xcode’s process for setting entitlements is quite complex, and it depends on various inputs, so it’s important to start by checking the output rather than looking at just the inputs.

        To check the entitlements in your binary run the following command:

        $ codesign -d --entitlements :- NetworkExtensionSample.app
        Executable=…/NetworkExtensionSample.app/NetworkExtensionSample
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" …>
        <plist version="1.0">
        <dict>
            <key>application-identifier</key>
            <string>SKMME9E2Y8.com.example.apple-samplecode.NetworkExtensionSample</string>
            <key>com.apple.developer.networking.vpn.api</key>
            <array>
                <string>allow-vpn</string>
            </array>
            <key>com.apple.developer.team-identifier</key>
            <string>SKMME9E2Y8</string>
            <key>get-task-allow</key>
            <true/>
        </dict>
        </plist>
        
        

        As you can see, this app is built with the com.apple.developer.networking.vpn.api set to an array of one item, allow-vpn.

        IMPORTANT This example is for a program to test the Personal VPN feature that we introduced with the original Network Extension framework in iOS 8.  The values will be different for an app using the new provider support that we added in iOS 9.  Specifically:

        • For a provider you’d expect to see the following entitlements:

          <key>com.apple.developer.networking.networkextension</key>
          <array>
            <string>packet-tunnel-provider</string>
            <string>app-proxy-provider</string>
            <string>content-filter-provider</string>
          </array>
          
          

          The array may be limited to some subset of the values shown.

        • For a hotspot helper you’d expect to see the following:

          <key>com.apple.developer.networking.HotspotHelper</key>
          <true/>
          
          
          

         

        Remember that, if your app has multiple executables, the main app and an extension say, you’ll have to check the entitlements on each one.  Specifically, if you’re using the com.apple.developer.networking.networkextension entitlement it must have the same value in both your app and your extension.

        Finding the Inputs

        If your entitlements are wrong you have to start looking at the inputs to Xcode’s code signing entitlement machinery:

        1. Start by looking at the build log for your executable (in Xcode, choose View > Navigators > Show Report Navigator, then select the appropriate build entry).

        2. Search the log for each code signing step (“Sign xxx”).
        3. Expand that step and you’ll see an entry like this:

         

        …
        Signing Identity:    "iPhone Developer: Quinn Quinn (7XFU7D52S4)"
        Provisioning Profile: "iOSTeam Provisioning Profile: com.example.apple-samplecode.NetworkExtensionSample"
                              (8d04addd-d7f5-4872-bd48-f6885bb67433)
        
        
        
        /usr/bin/codesign
            --force
            --sign 4735C927CF325B8BAF6E44E5EA9DE1860220A4E2
            --entitlements …/NetworkExtensionSample.app.xcent
            …/NetworkExtensionSample.app
        
        
        
        
        

        Note two things in this entry:

        • the UUID of the provisioning profile (8d04addd-d7f5-4872-bd48-f6885bb67433 in this example)

        • the path to the .xcent file

        These are the critical inputs to the code signing entitlement machinery and you’ll need to look at each in turn.

        Exploring the Profile

        Given the provisioning profile’s UUID, it’s relatively easy to find the profile: just look for it in ~/Library/MobileDevice/Provisioning Profiles/.

        $ ls -l ~/Library/MobileDevice/Provisioning\ Profiles/8d04addd-d7f5-4872-bd48-f6885bb67433.mobileprovision
        -rw-r--r--+ 1 quinn  staff  10720 14 May 13:22 /Users/quinn/Library/MobileDevice/Provisioning Profiles/8d04addd-d7f5-4872-bd48-f6885bb67433.mobileprovision
        
        

        You can use the following command to dump it:

        $ security cms -D -i ~/Library/MobileDevice/Provisioning\ Profiles/8d04addd-d7f5-4872-bd48-f6885bb67433.mobileprovision
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" …>
        <plist version="1.0">
        <dict>
            …
            <key>DeveloperCertificates</key>
            <array>
                …
            </array>
            <key>Entitlements</key>
            <dict>
                <key>keychain-access-groups</key>
                <array>
                    <string>SKMME9E2Y8.*</string> 
                </array>
                <key>get-task-allow</key>
                <true/>
                <key>application-identifier</key>
                <string>SKMME9E2Y8.com.example.apple-samplecode.NetworkExtensionSample</string>
                <key>com.apple.developer.team-identifier</key>
                <string>SKMME9E2Y8</string>
                <key>com.apple.developer.networking.vpn.api</key>
                <array>
                    <string>allow-vpn</string>
                </array>
        
            </dict>
            …
            <key>ProvisionedDevices</key>
            <array>
                …
            </array>
            …
            <key>UUID</key>
            <string>8d04addd-d7f5-4872-bd48-f6885bb67433</string>
            …
        </dict>
        </plist>
        
        

        There are two things to check here:

        • Check that the value of the UUID property is the UUID you’re looking for.

        • Check that the value of the Entitlements property makes sense.

        IMPORTANT You can think of these entitlements here as a ‘whitelist’.  That is, your app is allowed to use any entitlements listed here.  The values are not necessarily the exact values that will show up in the binary.  For example, your final app might have lots of different entries in the keychain-access-groups array.  Those final values also depend on the .xcent file.

        If the entitlements in the provisioning profile are wrong, you'll have to fix that in the Certificates, Identifiers & Profiles section of the developer web site.

        Exploring the Entitlements File

        The .xcent file shown above is built from your .entitlements file.  You should check the values in the .xcent file are what you expect.  For example:

        $ cat …/NetworkExtensionSample.app.xcent
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" …>
        <plist version="1.0">
        <dict>
            <key>application-identifier</key>
            <string>SKMME9E2Y8.com.example.apple-samplecode.NetworkExtensionSample</string>
            <key>com.apple.developer.networking.vpn.api</key>
            <array>
                <string>allow-vpn</string>
            </array>
            <key>com.apple.developer.team-identifier</key>
            <string>SKMME9E2Y8</string>
            <key>get-task-allow</key>
            <true/>
        </dict>
        </plist>
        
        

        If they’re wrong there are two potential sources of problems:

        • the input .entitlements file may be incorrect

        • Xcode might have failed to build the .xcent file correctly

        You can check that .entitlements file by looking at the build log again.  Look for a “Process product packaging” build step immediately above the “Sign xxx” step.  Expand it and you’ll see something like this:

        ProcessProductPackaging …
            …
            builtin-productPackagingUtility \
                …/NetworkExtensionSample.entitlements \
                -entitlements -format xml \
                -o …/NetworkExtensionSample.app.xcent
        
        

        The second path is the path to the built .xcent file.  The first path is the path to the .entitlements file that’s used to build that .xcent file.  You should check that the path to the .entitlements file is correct and that the contents of that file make sense.

        $ cat …/NetworkExtensionSample.entitlements
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" …>
        <plist version="1.0">
        <dict>
            <key>com.apple.developer.networking.vpn.api</key>
            <array>
                <string>allow-vpn</string>
            </array>
        </dict>
        </plist>
        
        

        If so, you can check the .xcent file that was built from it:

        $ cat …/NetworkExtensionSample.app.xcent
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" …>
        <plist version="1.0">
        <dict>
            <key>application-identifier</key>
            <string>SKMME9E2Y8.com.example.apple-samplecode.NetworkExtensionSample</string>
            <key>com.apple.developer.networking.vpn.api</key>
            <array>
                <string>allow-vpn</string>
            </array>
            <key>com.apple.developer.team-identifier</key>
            <string>SKMME9E2Y8</string>
            <key>get-task-allow</key>
            <true/>
        </dict>
        </plist>
        
        

        If the .entitlements file is correct but the .xcent file is wrong, you can usually fix this by doing a clean build of your project.

        Version History

        • 16 Jul 2015 — First version.

        • 16 Jul 2015 — Clarified that the com.apple.developer.networking.networkextension entitlement needs to be the same in both your app and your extension.

        • 16 Oct 2015 — Edited for DevForums.

        Share and Enjoy

        Quinn "The Eskimo!"
        Apple Developer Relations, Developer Technical Support, Core OS/Hardware
        let myEmail = "eskimo" + "1" + "@apple.com"