diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift index 7437c40..a2a229f 100644 --- a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift +++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift @@ -112,10 +112,10 @@ extension TunnelKitProvider { public let hostname: String /// The username. - public let username: String + public let username: String? /// The password. - public let password: String + public let password: String? /// :nodoc: public init(hostname: String, username: String, password: String) { @@ -128,19 +128,15 @@ extension TunnelKitProvider { guard let hostname = protocolConfiguration.serverAddress else { throw ProviderError.configuration(field: "protocolConfiguration.serverAddress") } - guard let username = protocolConfiguration.username else { - throw ProviderError.credentials(field: "protocolConfiguration.username") - } - guard let passwordReference = protocolConfiguration.passwordReference else { - throw ProviderError.credentials(field: "protocolConfiguration.passwordReference") - } - guard let password = try? Keychain.password(for: username, reference: passwordReference) else { - throw ProviderError.credentials(field: "protocolConfiguration.passwordReference (keychain)") - } self.hostname = hostname - self.username = username - self.password = password + if let username = protocolConfiguration.username, let passwordReference = protocolConfiguration.passwordReference { + self.username = username + password = try? Keychain.password(for: username, reference: passwordReference) + } else { + username = nil + password = nil + } } } @@ -488,17 +484,18 @@ extension TunnelKitProvider { public func generatedTunnelProtocol(withBundleIdentifier bundleIdentifier: String, appGroup: String, endpoint: AuthenticatedEndpoint) throws -> NETunnelProviderProtocol { let protocolConfiguration = NETunnelProviderProtocol() - let keychain = Keychain(group: appGroup) - do { - try keychain.set(password: endpoint.password, for: endpoint.username, label: Bundle.main.bundleIdentifier) - } catch _ { - throw ProviderError.credentials(field: "keychain.set()") - } - protocolConfiguration.providerBundleIdentifier = bundleIdentifier protocolConfiguration.serverAddress = endpoint.hostname - protocolConfiguration.username = endpoint.username - protocolConfiguration.passwordReference = try? keychain.passwordReference(for: endpoint.username) + if let username = endpoint.username, let password = endpoint.password { + let keychain = Keychain(group: appGroup) + do { + try keychain.set(password: password, for: username, label: Bundle.main.bundleIdentifier) + } catch _ { + throw ProviderError.credentials(field: "keychain.set()") + } + protocolConfiguration.username = username + protocolConfiguration.passwordReference = try? keychain.passwordReference(for: username) + } protocolConfiguration.providerConfiguration = generatedProviderConfiguration(appGroup: appGroup) return protocolConfiguration diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift index 2fa9076..d452af6 100644 --- a/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift +++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift @@ -210,11 +210,9 @@ open class TunnelKitProvider: NEPacketTunnelProvider { cfg.print(appVersion: appVersion) // log.info("Temporary CA is stored to: \(caPath)") - var sessionConfiguration = SessionProxy.ConfigurationBuilder( - username: endpoint.username, - password: endpoint.password, - caPath: caPath - ) + var sessionConfiguration = SessionProxy.ConfigurationBuilder(caPath: caPath) + sessionConfiguration.username = endpoint.username + sessionConfiguration.password = endpoint.password sessionConfiguration.cipher = cfg.cipher sessionConfiguration.digest = cfg.digest sessionConfiguration.clientCertificatePath = clientCertificatePath diff --git a/TunnelKit/Sources/Core/SessionProxy+Authenticator.swift b/TunnelKit/Sources/Core/SessionProxy+Authenticator.swift index f8e965d..54cd32b 100644 --- a/TunnelKit/Sources/Core/SessionProxy+Authenticator.swift +++ b/TunnelKit/Sources/Core/SessionProxy+Authenticator.swift @@ -62,18 +62,23 @@ extension SessionProxy { private(set) var serverRandom2: ZeroingData? - let username: ZeroingData + let username: ZeroingData? - let password: ZeroingData + let password: ZeroingData? - init(_ username: String, _ password: String) throws { + init(_ username: String?, _ password: String?) throws { preMaster = try SecureRandom.safeData(length: CoreConfiguration.preMasterLength) random1 = try SecureRandom.safeData(length: CoreConfiguration.randomLength) random2 = try SecureRandom.safeData(length: CoreConfiguration.randomLength) // XXX: not 100% secure, can't erase input username/password - self.username = Z(username, nullTerminated: true) - self.password = Z(password, nullTerminated: true) + if let username = username, let password = password { + self.username = Z(username, nullTerminated: true) + self.password = Z(password, nullTerminated: true) + } else { + self.username = nil + self.password = nil + } controlBuffer = Z() } @@ -93,8 +98,13 @@ extension SessionProxy { raw.appendSized(Z(UInt8(0))) // credentials - raw.appendSized(username) - raw.appendSized(password) + if let username = username, let password = password { + raw.appendSized(username) + raw.appendSized(password) + } else { + raw.append(Z(UInt16(0))) + raw.append(Z(UInt16(0))) + } // peer info raw.appendSized(Z(CoreConfiguration.peerInfo)) diff --git a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift index 9e82558..81ff4f5 100644 --- a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift +++ b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift @@ -113,10 +113,10 @@ extension SessionProxy { public struct ConfigurationBuilder { /// An username. - public let username: String + public var username: String? /// A password. - public let password: String + public var password: String? /// The cipher algorithm for data encryption. public var cipher: Cipher @@ -143,9 +143,9 @@ extension SessionProxy { public var renegotiatesAfter: TimeInterval? /// :nodoc: - public init(username: String, password: String, caPath: String) { - self.username = username - self.password = password + public init(caPath: String) { + username = nil + password = nil cipher = .aes128cbc digest = .sha1 self.caPath = caPath @@ -181,10 +181,10 @@ extension SessionProxy { public struct Configuration: Codable { /// - Seealso: `SessionProxy.ConfigurationBuilder.username` - public let username: String + public let username: String? /// - Seealso: `SessionProxy.ConfigurationBuilder.password` - public let password: String + public let password: String? /// - Seealso: `SessionProxy.ConfigurationBuilder.cipher` public let cipher: Cipher