Improve some things about OpenVPN.Configuration
- Treat empty passphrase as no passphrase - Parse authentication requirement from --auth-user-pass - Overload ConfigurationParser with String parameter - Move OpenVPN fallbacks inline with builder Give a withFallbacks: option to initialize basic fields rather than leaving them nil.
This commit is contained in:
parent
88544e4877
commit
c019cecbe0
|
@ -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/),
|
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).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Parse OpenVPN authentication requirement from `--auth-user-pass`.
|
||||||
|
|
||||||
## 4.1.0 (2022-02-09)
|
## 4.1.0 (2022-02-09)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -242,6 +242,9 @@ extension OpenVPN {
|
||||||
/// The tunnel MTU.
|
/// The tunnel MTU.
|
||||||
public var mtu: Int?
|
public var mtu: Int?
|
||||||
|
|
||||||
|
/// Requires username authentication.
|
||||||
|
public var authUserPass: Bool?
|
||||||
|
|
||||||
// MARK: Server
|
// MARK: Server
|
||||||
|
|
||||||
/// The auth-token returned by the server.
|
/// The auth-token returned by the server.
|
||||||
|
@ -300,7 +303,18 @@ extension OpenVPN {
|
||||||
/// Policies for redirecting traffic through the VPN gateway.
|
/// Policies for redirecting traffic through the VPN gateway.
|
||||||
public var routingPolicies: [RoutingPolicy]?
|
public var routingPolicies: [RoutingPolicy]?
|
||||||
|
|
||||||
public init() {
|
/**
|
||||||
|
Creates a `ConfigurationBuilder`.
|
||||||
|
|
||||||
|
- Parameter withFallbacks: If `true`, initializes builder with fallback values rather than nil.
|
||||||
|
*/
|
||||||
|
public init(withFallbacks: Bool = false) {
|
||||||
|
if withFallbacks {
|
||||||
|
cipher = Fallback.cipher
|
||||||
|
digest = Fallback.digest
|
||||||
|
compressionFraming = Fallback.compressionFraming
|
||||||
|
compressionAlgorithm = Fallback.compressionAlgorithm
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -332,6 +346,7 @@ extension OpenVPN {
|
||||||
randomizeEndpoint: randomizeEndpoint,
|
randomizeEndpoint: randomizeEndpoint,
|
||||||
usesPIAPatches: usesPIAPatches,
|
usesPIAPatches: usesPIAPatches,
|
||||||
mtu: mtu,
|
mtu: mtu,
|
||||||
|
authUserPass: authUserPass,
|
||||||
authToken: authToken,
|
authToken: authToken,
|
||||||
peerId: peerId,
|
peerId: peerId,
|
||||||
ipv4: ipv4,
|
ipv4: ipv4,
|
||||||
|
@ -348,24 +363,6 @@ extension OpenVPN {
|
||||||
routingPolicies: routingPolicies
|
routingPolicies: routingPolicies
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Shortcuts
|
|
||||||
|
|
||||||
public var fallbackCipher: Cipher {
|
|
||||||
return cipher ?? Fallback.cipher
|
|
||||||
}
|
|
||||||
|
|
||||||
public var fallbackDigest: Digest {
|
|
||||||
return digest ?? Fallback.digest
|
|
||||||
}
|
|
||||||
|
|
||||||
public var fallbackCompressionFraming: CompressionFraming {
|
|
||||||
return compressionFraming ?? Fallback.compressionFraming
|
|
||||||
}
|
|
||||||
|
|
||||||
public var fallbackCompressionAlgorithm: CompressionAlgorithm {
|
|
||||||
return compressionAlgorithm ?? Fallback.compressionAlgorithm
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The immutable configuration for `OpenVPNSession`.
|
/// The immutable configuration for `OpenVPNSession`.
|
||||||
|
@ -437,6 +434,9 @@ extension OpenVPN {
|
||||||
/// - Seealso: `ConfigurationBuilder.mtu`
|
/// - Seealso: `ConfigurationBuilder.mtu`
|
||||||
public let mtu: Int?
|
public let mtu: Int?
|
||||||
|
|
||||||
|
/// - Seealso: `ConfigurationBuilder.authUserPass`
|
||||||
|
public let authUserPass: Bool?
|
||||||
|
|
||||||
/// - Seealso: `ConfigurationBuilder.authToken`
|
/// - Seealso: `ConfigurationBuilder.authToken`
|
||||||
public let authToken: String?
|
public let authToken: String?
|
||||||
|
|
||||||
|
@ -502,15 +502,16 @@ extension OpenVPN.Configuration {
|
||||||
/**
|
/**
|
||||||
Returns a `ConfigurationBuilder` to use this configuration as a starting point for a new one.
|
Returns a `ConfigurationBuilder` to use this configuration as a starting point for a new one.
|
||||||
|
|
||||||
|
- Parameter withFallbacks: If `true`, initializes builder with fallback values rather than nil.
|
||||||
- Returns: An editable `ConfigurationBuilder` initialized with this configuration.
|
- Returns: An editable `ConfigurationBuilder` initialized with this configuration.
|
||||||
*/
|
*/
|
||||||
public func builder() -> OpenVPN.ConfigurationBuilder {
|
public func builder(withFallbacks: Bool = false) -> OpenVPN.ConfigurationBuilder {
|
||||||
var builder = OpenVPN.ConfigurationBuilder()
|
var builder = OpenVPN.ConfigurationBuilder()
|
||||||
builder.cipher = cipher
|
builder.cipher = cipher ?? (withFallbacks ? OpenVPN.Fallback.cipher : nil)
|
||||||
builder.dataCiphers = dataCiphers
|
builder.dataCiphers = dataCiphers
|
||||||
builder.digest = digest
|
builder.digest = digest ?? (withFallbacks ? OpenVPN.Fallback.digest : nil)
|
||||||
builder.compressionFraming = compressionFraming
|
builder.compressionFraming = compressionFraming ?? (withFallbacks ? OpenVPN.Fallback.compressionFraming : nil)
|
||||||
builder.compressionAlgorithm = compressionAlgorithm
|
builder.compressionAlgorithm = compressionAlgorithm ?? (withFallbacks ? OpenVPN.Fallback.compressionAlgorithm : nil)
|
||||||
builder.ca = ca
|
builder.ca = ca
|
||||||
builder.clientCertificate = clientCertificate
|
builder.clientCertificate = clientCertificate
|
||||||
builder.clientKey = clientKey
|
builder.clientKey = clientKey
|
||||||
|
@ -527,6 +528,7 @@ extension OpenVPN.Configuration {
|
||||||
builder.randomizeEndpoint = randomizeEndpoint
|
builder.randomizeEndpoint = randomizeEndpoint
|
||||||
builder.usesPIAPatches = usesPIAPatches
|
builder.usesPIAPatches = usesPIAPatches
|
||||||
builder.mtu = mtu
|
builder.mtu = mtu
|
||||||
|
builder.authUserPass = authUserPass
|
||||||
builder.authToken = authToken
|
builder.authToken = authToken
|
||||||
builder.peerId = peerId
|
builder.peerId = peerId
|
||||||
builder.ipv4 = ipv4
|
builder.ipv4 = ipv4
|
||||||
|
@ -549,7 +551,6 @@ extension OpenVPN.Configuration {
|
||||||
// MARK: Encoding
|
// MARK: Encoding
|
||||||
|
|
||||||
extension OpenVPN.Configuration {
|
extension OpenVPN.Configuration {
|
||||||
|
|
||||||
public func print() {
|
public func print() {
|
||||||
guard let endpointProtocols = endpointProtocols else {
|
guard let endpointProtocols = endpointProtocols else {
|
||||||
fatalError("No sessionConfiguration.endpointProtocols set")
|
fatalError("No sessionConfiguration.endpointProtocols set")
|
||||||
|
@ -558,6 +559,7 @@ extension OpenVPN.Configuration {
|
||||||
log.info("\tCipher: \(fallbackCipher)")
|
log.info("\tCipher: \(fallbackCipher)")
|
||||||
log.info("\tDigest: \(fallbackDigest)")
|
log.info("\tDigest: \(fallbackDigest)")
|
||||||
log.info("\tCompression framing: \(fallbackCompressionFraming)")
|
log.info("\tCompression framing: \(fallbackCompressionFraming)")
|
||||||
|
log.info("\tUsername authentication: \(authUserPass ?? false)")
|
||||||
if let compressionAlgorithm = compressionAlgorithm, compressionAlgorithm != .disabled {
|
if let compressionAlgorithm = compressionAlgorithm, compressionAlgorithm != .disabled {
|
||||||
log.info("\tCompression algorithm: \(compressionAlgorithm)")
|
log.info("\tCompression algorithm: \(compressionAlgorithm)")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -78,6 +78,8 @@ extension OpenVPN {
|
||||||
|
|
||||||
static let remote = NSRegularExpression("^remote +[^ ]+( +\\d+)?( +(udp[46]?|tcp[46]?))?")
|
static let remote = NSRegularExpression("^remote +[^ ]+( +\\d+)?( +(udp[46]?|tcp[46]?))?")
|
||||||
|
|
||||||
|
static let authUserPass = NSRegularExpression("^auth-user-pass")
|
||||||
|
|
||||||
static let eku = NSRegularExpression("^remote-cert-tls +server")
|
static let eku = NSRegularExpression("^remote-cert-tls +server")
|
||||||
|
|
||||||
static let remoteRandom = NSRegularExpression("^remote-random")
|
static let remoteRandom = NSRegularExpression("^remote-random")
|
||||||
|
@ -178,7 +180,7 @@ extension OpenVPN {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Parses an .ovpn file from an URL.
|
Parses a configuration from a .ovpn file.
|
||||||
|
|
||||||
- Parameter url: The URL of the configuration file.
|
- Parameter url: The URL of the configuration file.
|
||||||
- Parameter passphrase: The optional passphrase for encrypted data.
|
- Parameter passphrase: The optional passphrase for encrypted data.
|
||||||
|
@ -187,8 +189,39 @@ extension OpenVPN {
|
||||||
- Throws: `ConfigurationError` if the configuration file is wrong or incomplete.
|
- Throws: `ConfigurationError` if the configuration file is wrong or incomplete.
|
||||||
*/
|
*/
|
||||||
public static func parsed(fromURL url: URL, passphrase: String? = nil, returnsStripped: Bool = false) throws -> Result {
|
public static func parsed(fromURL url: URL, passphrase: String? = nil, returnsStripped: Bool = false) throws -> Result {
|
||||||
let lines = try String(contentsOf: url).trimmedLines()
|
let contents = try String(contentsOf: url)
|
||||||
return try parsed(fromLines: lines, isClient: true, passphrase: passphrase, originalURL: url, returnsStripped: returnsStripped)
|
return try parsed(
|
||||||
|
fromContents: contents,
|
||||||
|
passphrase: passphrase,
|
||||||
|
originalURL: url,
|
||||||
|
returnsStripped: returnsStripped
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Parses a configuration from a string.
|
||||||
|
|
||||||
|
- Parameter contents: The contents of the configuration file.
|
||||||
|
- Parameter passphrase: The optional passphrase for encrypted data.
|
||||||
|
- Parameter originalURL: The optional original URL of the configuration file.
|
||||||
|
- Parameter returnsStripped: When `true`, stores the stripped file into `Result.strippedLines`. Defaults to `false`.
|
||||||
|
- Returns: The `Result` outcome of the parsing.
|
||||||
|
- Throws: `ConfigurationError` if the configuration file is wrong or incomplete.
|
||||||
|
*/
|
||||||
|
public static func parsed(
|
||||||
|
fromContents contents: String,
|
||||||
|
passphrase: String? = nil,
|
||||||
|
originalURL: URL? = nil,
|
||||||
|
returnsStripped: Bool = false
|
||||||
|
) throws -> Result {
|
||||||
|
let lines = contents.trimmedLines()
|
||||||
|
return try parsed(
|
||||||
|
fromLines: lines,
|
||||||
|
isClient: true,
|
||||||
|
passphrase: passphrase,
|
||||||
|
originalURL: originalURL,
|
||||||
|
returnsStripped: returnsStripped
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,7 +235,13 @@ extension OpenVPN {
|
||||||
- Returns: The `Result` outcome of the parsing.
|
- Returns: The `Result` outcome of the parsing.
|
||||||
- Throws: `ConfigurationError` if the configuration file is wrong or incomplete.
|
- Throws: `ConfigurationError` if the configuration file is wrong or incomplete.
|
||||||
*/
|
*/
|
||||||
public static func parsed(fromLines lines: [String], isClient: Bool = false, passphrase: String? = nil, originalURL: URL? = nil, returnsStripped: Bool = false) throws -> Result {
|
public static func parsed(
|
||||||
|
fromLines lines: [String],
|
||||||
|
isClient: Bool = false,
|
||||||
|
passphrase: String? = nil,
|
||||||
|
originalURL: URL? = nil,
|
||||||
|
returnsStripped: Bool = false
|
||||||
|
) throws -> Result {
|
||||||
var optStrippedLines: [String]? = returnsStripped ? [] : nil
|
var optStrippedLines: [String]? = returnsStripped ? [] : nil
|
||||||
var optWarning: ConfigurationError?
|
var optWarning: ConfigurationError?
|
||||||
var unsupportedError: ConfigurationError?
|
var unsupportedError: ConfigurationError?
|
||||||
|
@ -229,6 +268,7 @@ extension OpenVPN {
|
||||||
var optDefaultProto: SocketType?
|
var optDefaultProto: SocketType?
|
||||||
var optDefaultPort: UInt16?
|
var optDefaultPort: UInt16?
|
||||||
var optRemotes: [(String, UInt16?, SocketType?)] = [] // address, port, socket
|
var optRemotes: [(String, UInt16?, SocketType?)] = [] // address, port, socket
|
||||||
|
var authUserPass = false
|
||||||
var optChecksEKU: Bool?
|
var optChecksEKU: Bool?
|
||||||
var optRandomizeEndpoint: Bool?
|
var optRandomizeEndpoint: Bool?
|
||||||
var optMTU: Int?
|
var optMTU: Int?
|
||||||
|
@ -537,6 +577,10 @@ extension OpenVPN {
|
||||||
}
|
}
|
||||||
optMTU = Int(str)
|
optMTU = Int(str)
|
||||||
}
|
}
|
||||||
|
Regex.authUserPass.enumerateComponents(in: line) { _ in
|
||||||
|
isHandled = true
|
||||||
|
authUserPass = true
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: Server
|
// MARK: Server
|
||||||
|
|
||||||
|
@ -687,10 +731,11 @@ extension OpenVPN {
|
||||||
sessionBuilder.compressionAlgorithm = optCompressionAlgorithm
|
sessionBuilder.compressionAlgorithm = optCompressionAlgorithm
|
||||||
sessionBuilder.ca = optCA
|
sessionBuilder.ca = optCA
|
||||||
sessionBuilder.clientCertificate = optClientCertificate
|
sessionBuilder.clientCertificate = optClientCertificate
|
||||||
|
sessionBuilder.authUserPass = authUserPass
|
||||||
|
|
||||||
if let clientKey = optClientKey, clientKey.isEncrypted {
|
if let clientKey = optClientKey, clientKey.isEncrypted {
|
||||||
// FIXME: remove dependency on TLSBox
|
// FIXME: remove dependency on TLSBox
|
||||||
guard let passphrase = passphrase else {
|
guard let passphrase = passphrase, !passphrase.isEmpty else {
|
||||||
throw ConfigurationError.encryptionPassphrase
|
throw ConfigurationError.encryptionPassphrase
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
@ -746,6 +791,7 @@ extension OpenVPN {
|
||||||
sessionBuilder.hostname = nil
|
sessionBuilder.hostname = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sessionBuilder.authUserPass = authUserPass
|
||||||
sessionBuilder.checksEKU = optChecksEKU
|
sessionBuilder.checksEKU = optChecksEKU
|
||||||
sessionBuilder.randomizeEndpoint = optRandomizeEndpoint
|
sessionBuilder.randomizeEndpoint = optRandomizeEndpoint
|
||||||
sessionBuilder.mtu = optMTU
|
sessionBuilder.mtu = optMTU
|
||||||
|
|
Loading…
Reference in New Issue