Debugging Entitlement Issues

This thread has been locked by a moderator.

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 ***”).
  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 ***” 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"
Up vote post of eskimo
15k views