NEVPNErrorConfigurationReadWriteFailed upon loadFromPreferencesWithCompletionHandler:

ISSUE


Our SDK leverages built-in iOS IPSec engine and is built on top of NetworkExtension framework.


One of our SDK's users complained about not being able to connect to VPN on his device(s). From the logs we he sent, we saw this:


Method `loadFromPreferencesWithCompletionHandler:` failed (error: Error Domain=NEVPNErrorDomain Code=5 "permission denied" UserInfo={NSLocalizedDescription=permission denied}).


He also reported an absense of VPN profile in Settings.app.


Looking through our code we see that this log message is posted in the loadFromPreferencesWithCompletionHandler: callback of NEVPNManager's instance. Error code seems to correspond to NEVPNErrorConfigurationReadWriteFailed = 5


ATTEMPTS TO FIX


We cannot reproduce it on our end, so I have done two things to investigate the cause:


1) entitlement in Provision Profile -- it has "allow-vpn". Moreover, an app bundle provisioned with the same profile works for us, but does not work for the user

2) Using Apple Configurator 2, I supervised my device and added a configuration profile with A) a restriction to add Configuration profiles B) a restriction to add VPN profiles. Anazingly, I still can add VPN profile to my device from the very same app. VPN does work.


At this point, I'm really confized what to do here. Can anybody please give me a clue?

Accepted Reply

OK, I was finally able to figure this out.


After creating new Provision Profiles (not just updating the old ones) for the app (of course, with Personal VPN entitlement attached to it), everything started to work (magic!).


Probably, something went wrong with caching provision profile on that particular development device. I don't know, but it works after new build provisioned by new profiles.

Replies

1) entitlement in Provision Profile

Be aware that the provisioning profile is only one part of the entitlement story. Entitlements are baked in to the app at compile time, so you need to verify the entitlements of the built app.

In your situation I recommend the following:

  1. Have your customer build and archive an app and then generate an ad hoc

    .ipa
    .
  2. Have them verify that this

    .ipa
    , when installed on the device, still has the problem.
  3. Have them send you that

    .ipa
    .
  4. Once you get it, unpack it (it’s actually a

    .zip
    file) and then dump the entitlements of the enclosed app.
    $ codesign -d --entilements :- /path/to/the.app

    .

  5. For good measure you can dump the provisioning profile within the app.

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

    .

This will tell you whether the app has the correct entitlements and whether they’re being correctly whitelisted by the associated profile.

ps For more info on entitlement debugging see Technote 2415 Entitlements Troubleshooting.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi eskimo,


Thank you for quick response.


I do have access to IPA with our SDK, the users have issue with. Unfortunatelly, comparing application and provision profile entitlements didn't revealed the cause of the issue. They both have allow-vpn


com.apple.developer.networking.vpn.api

allow-vpn



Any other ideas?


P.S.: Forget to mention,


1) users report it from iPhone 5C with iOS 10.3.3.

2) also, I see this message in logs tight before error code 5:


Failed to load configurations: Error Domain=NEConfigurationErrorDomain Code=10 "permission denied" UserInfo={NSLocalizedDescription=permission denied}


Thank you.

So what API-level action triggers this failure? Specifically:

  • It is them trying to load a configuration created via a profile?

  • Create a new configuration?

  • Load a configuration that they previously created?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

That's when the app creates a profile for the first time. We call NEVPNManager's


- (void)loadFromPreferencesWithCompletionHandler:(void (^)(NSError * __nullable error))completionHandler


When it suceedes, user sees iOS system dialog "<app_name> Would Like to Add VPN Configuration". However, I suspect that does not happen for our user, because he reports there is no VPN profile in Settings.app -> General -> VPN.


I am thiking about any kind of check prior to this method call and additional logging around this logic. However, I lack an idea.



That's when the app creates a profile for the first time. We call NEVPNManager's

-loadFromPreferencesWithCompletionHandler:

In this scenario, were you expecting the load to return a complete configuration (because it’s been pre-configured via a configuration profile) or return a default configuration (because the user is starting from scratch).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

User is starting from scratch and, as reported, never saw the "<app_name> Would Like to Add VPN Configurations" prompt. Subsequently, there is no profile being installed into iOS.

OK, well, I’m out of simple ideas at this point. If you want to dig deeper into this you should open a DTS tech support incident and I can take a look in that context.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

OK, I was finally able to figure this out.


After creating new Provision Profiles (not just updating the old ones) for the app (of course, with Personal VPN entitlement attached to it), everything started to work (magic!).


Probably, something went wrong with caching provision profile on that particular development device. I don't know, but it works after new build provisioned by new profiles.