Reputation: 69
I'm trying to to install the profile to create a VPN connection using Swift. It creates a VPN connection but I'm getting the following error and I'm not able to connect using that VPN connection.
SecItemCopyMatching failed: -50
There is some issue with the keychain save-retrieve data but not getting exactly.
Here is the code:
installVPNProfile(){
let server: String? = "127.0.0.1"
let username: String? = "MyServer"
var _: String? = ""
var _: String? = ""
// Save password & psk
//var password_Data = KeyChain.stringToNSDATA(string:"password")
keychain.set(("12345").data(using: .utf8)!, forKey: "VPN_PASSWORD")
keychain.set(("12345abcde").data(using: .utf8)!, forKey: "PSK")
vpnManager.loadFromPreferences(completionHandler: {(_ error: Error?) -> Void in
if error != nil {
print("Load config failed [\(String(describing: error?.localizedDescription))]")
return
}
var p: NEVPNProtocolIPSec? = (vpnManager.protocolConfiguration as? NEVPNProtocolIPSec)
if p != nil {
// Protocol exists.
// If you don't want to edit it, just return here.
}
else {
// create a new one.
p = NEVPNProtocolIPSec()
}
// config IPSec protocol
p?.username = username
p?.serverAddress = server
p?.passwordReference = self.keychain.getData("VPN_PASSWORD") // PSK
p?.authenticationMethod = authentication type
p?.sharedSecretReference = self.keychain.getData("PSK")
p?.useExtendedAuthentication = true
p?.disconnectOnSleep = false
self.vpnManager.protocolConfiguration = p
self.vpnManager.localizedDescription = "VPN Demo"
self.vpnManager.isEnabled = true
self.vpnManager.saveToPreferences(completionHandler: {(_ error: Error?) -> Void in
if error != nil {
print("Save config failed [\(error?.localizedDescription)]")
}
})
})
}
Upvotes: 0
Views: 590
Reputation: 6579
The shared secret reference and the password reference should not be the secret data itself, but should be a persistence reference to the data.
When you set the passwordReference
, you give it the data that is returned from the getData
function:
p?.passwordReference = self.keychain.getData("VPN_PASSWORD")
You do the same when setting the sharedSecretReference
. I don't know what code you are using that is wrapping the keychain code, but there should be a function that returns the reference, not the data itself. If your wrapper code doesn't have this function, you should use a Keychain library the does support this, or create it yourself.
You can get this persistent reference when you query the keychain by setting the kSecReturnPersistentRef
key to true
. The data you get back from this query is then the persistent reference, not the secret. The VPN framework will use this reference to fetch the data from the keychain when starting the VPN connection.
Check out this example how to create and reference secrets for a VPN profile: http://blog.moatazthenervous.com/create-a-key-chain-for-apples-vpn/
Upvotes: 1