ss-abramchuk / OpenVPNAdapter

Objective-C wrapper for OpenVPN library. Compatible with iOS and macOS.
GNU Affero General Public License v3.0
482 stars 217 forks source link

How do I access the VPN password to pass into the OpenVPNCredentials? #98

Closed agrigg closed 6 years ago

agrigg commented 6 years ago

The ReadMe shows the following code

// If your VPN configuration requires user credentials you can provide them by
// `protocolConfiguration.username` and `protocolConfiguration.passwordReference`
// properties. It is recommended to use persistent keychain reference to a keychain
// item containing the password.

guard let username: String = protocolConfiguration.username else {
    fatalError()
}

// Retrieve a password from the keychain
guard let password: String = ... {
    fatalError()
}

I'm able to pull the username from the protocolConfiguration without any issues.

But the sample doesn't show how to convert the protocolConfiguration.passwordReference to a String to pass off to the OpenVPNCredentials. How do I take the password reference and get the password as a string?

agrigg commented 6 years ago

I was able to resolve this by turning on Keychain Sharing between my main app and the Packet Tunnel Provider and then looking up the password from the keychain. I ended up just pulling the password using the username as the key, but if anyone needs to get the value of the password using the persistent ref this code worked for me:

func passwordForPersistentRef(passwordRef: Data) -> String? {
    let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                                kSecAttrService as String: "[YourService]",
                                kSecAttrAccessGroup as String: "[TeamID].[KeychainSharingGroupName]",
                                kSecMatchItemList as String: [passwordRef] as CFArray,
                                kSecMatchLimit as String: kSecMatchLimitOne,
                                kSecReturnData as String: true]

    var result: AnyObject?
    var password: String?

    let resultCodeLoad = withUnsafeMutablePointer(to: &result) {
        SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
    }

    if resultCodeLoad == noErr {
        if let result = result as? Data {
            password = NSString(data: result, encoding: String.Encoding.utf8.rawValue) as? String
        }
    } else {
        print("Error loading from Keychain: \(resultCodeLoad)")
    }

    return password;
}