I have the following code that is attempting to set up Hotspot 2.0 using an EAP-TLS configuration. I am importing a pk12 file and using those certificates.
I have tried all manner of permutations for the configuration, and have narrowed down all the errors I was getting and now I am just getting a generic:
Error: invalid EAP settings.
I have tried adding the identity separately and either get an entitlements issue which I can't figure out why since I have added the required network extension sharing groups, or a duplicate item error, meaning it was already correctly added.
The certificate and configuration are correctly working through an Android app already.
static let accessGroup: String? = {
guard let prefix = Bundle.main.object(forInfoDictionaryKey: "AppIdentifierPrefix") as? String else {
print("Could not load group")
return nil
}
return "\(prefix)com.apple.networkextensionsharing"
}()
static func setupHotspot(data: CertificateData) {
let h20 = NEHotspotHS20Settings(domainName: data.realm, roamingEnabled: false)
h20.naiRealmNames = [data.realm]
var result: CFArray?
let options: [CFString: Any] = [
kSecImportExportPassphrase: "**********",
kSecAttrLabel: "ident:\(data.user)",
kSecAttrAccessGroup: accessGroup!,
kSecReturnPersistentRef: true
]
let status = SecPKCS12Import(data.p12 as CFData, options as CFDictionary, &result)
guard status == errSecSuccess,
let importResult = result as? [[String: Any]],
let resultDict = importResult.first else {
print("P12 Import failed: \(status)")
return
}
let identity = resultDict[kSecImportItemIdentity as String] as! SecIdentity
let eap = NEHotspotEAPSettings()
eap.supportedEAPTypes = [NEHotspotEAPSettings.EAPType.EAPTLS.rawValue as NSNumber]
eap.isTLSClientCertificateRequired = true
eap.trustedServerNames = [ data.realm ]
eap.outerIdentity = "anonymous"
guard eap.setIdentity( identity ) else {
print("setIdentity failed")
return
}
let configuration = NEHotspotConfiguration(hs20Settings: h20, eapSettings: eap)
NEHotspotConfigurationManager.shared.apply(configuration) { error in
if let error = error {
print("Error: \(error.localizedDescription)")
} else {
print("Success")
}
}
}
Are you sure that your accessGroup calculation is working as expected? AppIdentifierPrefix isn’t a standard Info.plist key, so for this to work you must be adding it to your Info.plist yourself.
Also, is your app using a unique App ID prefix? Or your Team ID as the App ID prefix? The docs say to use the Team ID, but I think that’s a case of them just assuming the modern world where the App ID prefix is always the Team ID. If you’re using is using a unique App ID prefix I’m not entirely sure what’ll happen, so lemme know in that case.
I have tried adding the identity separately
You’ll definitely need to do that. The keys you’re passing to SecPKCS12Import, kSecAttrAccessGroup and kSecReturnPersistentRef, don’t do what you’re hoping they’ll do (I suspect they’re just being ignored).
My advice is that you call SecPKCS12Import and then call SecItemAdd.
If that process is failing, it’s likely that you’re falling in to one of the many pitfalls of the SecItem API. I talk about this in depth in:
Pasted in at the end of this reply you’ll find two snippets of code that I used to test this stuff:
importIdentityAction()shows how to import the identity, add it to the keychain, and set it onNEHotspotEAPSettings.resetAction()shows how to wipe the keychain, so you can start from scratch between tests. This is useful when wrangling problems like this, because it avoids the complexities of handling keychain item uniqueness in your test app. In a real app, you do have to wrangle with that complexity, which is not helped by the fact that digital identities aren’t real (see the above posts for an explanation of that comment).
Oh, and these snippets rely on the identityNamed(…) routine, which you can find on this thread.
now I am just getting a generic
Right. My experience is that this error is usually accompanied by a system log entry with more details. Specifically, look for log entries with com.apple.networkextension as the subsystem. So, once you’ve got your keychain stuff sorted out, if you’re still getting this error, monitor the system log during the failure and see what you get.
If you’re not familiar with the system log, have a read of Your Friend the System Log.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
func importIdentityAction() {
do {
print("will set identity")
let identity = Bundle.main.identityNamed("Benjy", password: "test")!
try secCall {
SecItemAdd([
kSecValueRef: identity,
kSecAttrAccessGroup: "SKMME9E2Y8.com.apple.networkextensionsharing",
] as NSDictionary, nil)
}
let eap = NEHotspotEAPSettings()
let success = eap.setIdentity(identity)
if success {
print("did set identity")
} else {
print("did not set identity")
}
} catch {
print("did not set identity, error: \(error)")
}
}
func resetAction() {
print("will reset")
_ = SecItemDelete([kSecClass: kSecClassCertificate] as NSDictionary)
_ = SecItemDelete([kSecClass: kSecClassKey] as NSDictionary)
print("did reset")
}