diff --git a/CHANGELOG.md b/CHANGELOG.md index 0efde3c..0e30536 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Fixed + +- Keychain may fail to set password. [#327](https://github.com/passepartoutvpn/tunnelkit/issues/327) + ## 6.1.0 (2023-07-05) ### Changed diff --git a/Sources/TunnelKitManager/Keychain.swift b/Sources/TunnelKitManager/Keychain.swift index e93c780..4056fc9 100644 --- a/Sources/TunnelKitManager/Keychain.swift +++ b/Sources/TunnelKitManager/Keychain.swift @@ -82,7 +82,7 @@ public class Keychain { - Parameter userDefined: Optional user-defined data. - Parameter label: An optional label. - Returns: The reference to the password. - - Throws: `KeychainError.add` if unable to add the password to the keychain. + - Throws: `TunnelKitManagerError.keychain` if unable to add the password to the keychain. **/ @discardableResult public func set(password: String, for username: String, context: String, userDefined: String? = nil, label: String? = nil) throws -> Data { @@ -92,14 +92,20 @@ public class Keychain { return try passwordReference(for: username, context: context) } removePassword(for: username, context: context) - } catch let error as KeychainError { + } catch let error as TunnelKitManagerError { - // rethrow cancelation - if error == .userCancelled { + // this is a well-known error from password() or passwordReference(), keep going + + // rethrow cancellation + if case .keychain(.userCancelled) = error { throw error } // otherwise, no pre-existing password + } catch { + + // IMPORTANT: rethrow any other unknown error (leave this code explicit) + throw error } var query = [String: Any]() @@ -144,7 +150,7 @@ public class Keychain { - Parameter context: The context. - Parameter userDefined: Optional user-defined data. - Returns: The password for the input username. - - Throws: `KeychainError.notFound` if unable to find the password in the keychain. + - Throws: `TunnelKitManagerError.keychain` if unable to find the password in the keychain. **/ public func password(for username: String, context: String, userDefined: String? = nil) throws -> String { var query = [String: Any]() @@ -181,7 +187,7 @@ public class Keychain { - Parameter context: The context. - Parameter userDefined: Optional user-defined data. - Returns: The password reference for the input username. - - Throws: `KeychainError.notFound` if unable to find the password in the keychain. + - Throws: `TunnelKitManagerError.keychain` if unable to find the password in the keychain. **/ public func passwordReference(for username: String, context: String, userDefined: String? = nil) throws -> Data { var query = [String: Any]() @@ -213,7 +219,7 @@ public class Keychain { - Parameter reference: The password reference. - Returns: The password for the input reference. - - Throws: `KeychainError.notFound` if unable to find the password in the keychain. + - Throws: `TunnelKitManagerError.keychain` if unable to find the password in the keychain. **/ public static func password(forReference reference: Data) throws -> String { var query = [String: Any]() @@ -250,7 +256,7 @@ public class Keychain { - Parameter identifier: The unique identifier. - Parameter data: The public key data. - Returns: The `SecKey` object representing the public key. - - Throws: `KeychainError.add` if unable to add the public key to the keychain. + - Throws: `TunnelKitManagerError.keychain` if unable to add the public key to the keychain. **/ public func add(publicKeyWithIdentifier identifier: String, data: Data) throws -> SecKey { var query = [String: Any]() @@ -275,7 +281,7 @@ public class Keychain { - Parameter identifier: The unique identifier. - Returns: The `SecKey` object representing the public key. - - Throws: `KeychainError.notFound` if unable to find the public key in the keychain. + - Throws: `TunnelKitManagerError.keychain` if unable to find the public key in the keychain. **/ public func publicKey(withIdentifier identifier: String) throws -> SecKey { var query = [String: Any]()