Convert a boolean value to enum for connecting to self-signed certificate FTPS server
> define an enum like Alamofire's ServerTrustPolicy
This commit is contained in:
@@ -68,8 +68,8 @@ public class FileProviderStreamTask: URLSessionTask, StreamDelegate {
|
||||
return FileProviderStreamTask.streamTasks[_taskIdentifier]
|
||||
}
|
||||
|
||||
/// Trust all certificates if true, Otherwise validate certificate chain.
|
||||
public var trustAllCertificates: Bool = false
|
||||
/// Trust all certificates if `disableEvaluation`, Otherwise validate certificate chain.
|
||||
public var serverTrustPolicy: ServerTrustPolicy = .performDefaultEvaluation(validateHost: true)
|
||||
|
||||
/**
|
||||
* An identifier uniquely identifies the task within a given session.
|
||||
@@ -418,7 +418,7 @@ public class FileProviderStreamTask: URLSessionTask, StreamDelegate {
|
||||
inputStream.setProperty(securityLevel.rawValue, forKey: .socketSecurityLevelKey)
|
||||
outputStream.setProperty(securityLevel.rawValue, forKey: .socketSecurityLevelKey)
|
||||
|
||||
if trustAllCertificates {
|
||||
if serverTrustPolicy.evaluate() {
|
||||
// ※ Called, After setProperty securityLevel
|
||||
addTrustAllCertificatesSettings()
|
||||
}
|
||||
@@ -638,7 +638,7 @@ public class FileProviderStreamTask: URLSessionTask, StreamDelegate {
|
||||
isSecure = true
|
||||
if let inputStream = self.inputStream, let outputStream = self.outputStream,
|
||||
inputStream.property(forKey: .socketSecurityLevelKey) as? String == StreamSocketSecurityLevel.none.rawValue {
|
||||
if self.trustAllCertificates {
|
||||
if serverTrustPolicy.evaluate() {
|
||||
// ※ Called, Before setProperty securityLevel
|
||||
self.addTrustAllCertificatesSettings()
|
||||
}
|
||||
|
||||
@@ -217,10 +217,10 @@ open class FTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOpera
|
||||
public var securedDataConnection: Bool = true
|
||||
|
||||
/**
|
||||
Trust all certificates if true, Otherwise validate certificate chain.
|
||||
Default is `false`.
|
||||
Trust all certificates if `disableEvaluation`, Otherwise validate certificate chain.
|
||||
Default is `performDefaultEvaluation`.
|
||||
*/
|
||||
public var trustAllCertificates: Bool = false
|
||||
public var serverTrustPolicy: ServerTrustPolicy = .performDefaultEvaluation(validateHost: true)
|
||||
|
||||
open func contentsOfDirectory(path: String, completionHandler: @escaping ([FileObject], Error?) -> Void) {
|
||||
self.contentsOfDirectory(path: path, rfc3659enabled: supportsRFC3659, completionHandler: completionHandler)
|
||||
@@ -241,7 +241,7 @@ open class FTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOpera
|
||||
let path = ftpPath(apath)
|
||||
|
||||
let task = session.fpstreamTask(withHostName: baseURL!.host!, port: baseURL!.port!)
|
||||
task.trustAllCertificates = trustAllCertificates
|
||||
task.serverTrustPolicy = serverTrustPolicy
|
||||
self.ftpLogin(task) { (error) in
|
||||
if let error = error {
|
||||
self.dispatch_queue.async {
|
||||
@@ -297,7 +297,7 @@ open class FTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOpera
|
||||
let path = ftpPath(apath)
|
||||
|
||||
let task = session.fpstreamTask(withHostName: baseURL!.host!, port: baseURL!.port!)
|
||||
task.trustAllCertificates = trustAllCertificates
|
||||
task.serverTrustPolicy = serverTrustPolicy
|
||||
self.ftpLogin(task) { (error) in
|
||||
if let error = error {
|
||||
self.dispatch_queue.async {
|
||||
@@ -470,7 +470,7 @@ open class FTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOpera
|
||||
progress.setUserInfoObject(Progress.FileOperationKind.downloading, forKey: .fileOperationKindKey)
|
||||
|
||||
let task = session.fpstreamTask(withHostName: baseURL!.host!, port: baseURL!.port!)
|
||||
task.trustAllCertificates = trustAllCertificates
|
||||
task.serverTrustPolicy = serverTrustPolicy
|
||||
self.ftpLogin(task) { (error) in
|
||||
if let error = error {
|
||||
self.dispatch_queue.async {
|
||||
@@ -521,7 +521,7 @@ open class FTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOpera
|
||||
progress.setUserInfoObject(Progress.FileOperationKind.downloading, forKey: .fileOperationKindKey)
|
||||
|
||||
let task = session.fpstreamTask(withHostName: baseURL!.host!, port: baseURL!.port!)
|
||||
task.trustAllCertificates = trustAllCertificates
|
||||
task.serverTrustPolicy = serverTrustPolicy
|
||||
self.ftpLogin(task) { (error) in
|
||||
if let error = error {
|
||||
self.dispatch_queue.async {
|
||||
@@ -585,7 +585,7 @@ open class FTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOpera
|
||||
progress.setUserInfoObject(Progress.FileOperationKind.downloading, forKey: .fileOperationKindKey)
|
||||
|
||||
let task = session.fpstreamTask(withHostName: baseURL!.host!, port: baseURL!.port!)
|
||||
task.trustAllCertificates = trustAllCertificates
|
||||
task.serverTrustPolicy = serverTrustPolicy
|
||||
self.ftpLogin(task) { (error) in
|
||||
if let error = error {
|
||||
self.dispatch_queue.async {
|
||||
@@ -640,7 +640,7 @@ open class FTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOpera
|
||||
progress.setUserInfoObject(Progress.FileOperationKind.downloading, forKey: .fileOperationKindKey)
|
||||
|
||||
let task = session.fpstreamTask(withHostName: baseURL!.host!, port: baseURL!.port!)
|
||||
task.trustAllCertificates = trustAllCertificates
|
||||
task.serverTrustPolicy = serverTrustPolicy
|
||||
self.ftpLogin(task) { (error) in
|
||||
if let error = error {
|
||||
self.dispatch_queue.async {
|
||||
@@ -703,7 +703,7 @@ open class FTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOpera
|
||||
progress.setUserInfoObject(Progress.FileOperationKind.downloading, forKey: .fileOperationKindKey)
|
||||
|
||||
let task = session.fpstreamTask(withHostName: baseURL!.host!, port: baseURL!.port!)
|
||||
task.trustAllCertificates = trustAllCertificates
|
||||
task.serverTrustPolicy = serverTrustPolicy
|
||||
self.ftpLogin(task) { (error) in
|
||||
if let error = error {
|
||||
self.dispatch_queue.async {
|
||||
@@ -785,7 +785,7 @@ extension FTPFileProvider {
|
||||
progress.setUserInfoObject(Progress.FileOperationKind.downloading, forKey: .fileOperationKindKey)
|
||||
|
||||
let task = session.fpstreamTask(withHostName: baseURL!.host!, port: baseURL!.port!)
|
||||
task.trustAllCertificates = trustAllCertificates
|
||||
task.serverTrustPolicy = serverTrustPolicy
|
||||
self.ftpLogin(task) { (error) in
|
||||
if let error = error {
|
||||
completionHandler?(error)
|
||||
|
||||
@@ -194,7 +194,7 @@ internal extension FTPFileProvider {
|
||||
|
||||
let passiveTask = self.session.fpstreamTask(withHostName: host, port: port)
|
||||
if self.baseURL?.scheme == "ftps" || self.baseURL?.scheme == "ftpes" || self.baseURL?.port == 990 {
|
||||
passiveTask.trustAllCertificates = task.trustAllCertificates
|
||||
passiveTask.serverTrustPolicy = task.serverTrustPolicy
|
||||
passiveTask.startSecureConnection()
|
||||
}
|
||||
passiveTask.securityLevel = .tlSv1
|
||||
@@ -238,7 +238,7 @@ internal extension FTPFileProvider {
|
||||
|
||||
let passiveTask = self.session.fpstreamTask(withHostName: host, port: port)
|
||||
if self.baseURL?.scheme == "ftps" || self.baseURL?.scheme == "ftpes" || self.baseURL?.port == 990 {
|
||||
passiveTask.trustAllCertificates = task.trustAllCertificates
|
||||
passiveTask.serverTrustPolicy = task.serverTrustPolicy
|
||||
passiveTask.startSecureConnection()
|
||||
}
|
||||
passiveTask.securityLevel = .tlSv1
|
||||
@@ -260,7 +260,7 @@ internal extension FTPFileProvider {
|
||||
}
|
||||
let activeTask = self.session.fpstreamTask(withNetService: service)
|
||||
if self.baseURL?.scheme == "ftps" || self.baseURL?.port == 990 {
|
||||
activeTask.trustAllCertificates = task.trustAllCertificates
|
||||
activeTask.serverTrustPolicy = task.serverTrustPolicy
|
||||
activeTask.startSecureConnection()
|
||||
}
|
||||
activeTask.resume()
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// ServerTrustPolicy.swift
|
||||
//
|
||||
// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// MARK: - ServerTrustPolicy
|
||||
/// The `ServerTrustPolicy` evaluates the server trust generally provided by an `NSURLAuthenticationChallenge` when
|
||||
/// connecting to a server over a secure HTTPS connection. The policy configuration then evaluates the server trust
|
||||
/// with a given set of criteria to determine whether the server trust is valid and the connection should be made.
|
||||
///
|
||||
/// Using pinned certificates or public keys for evaluation helps prevent man-in-the-middle (MITM) attacks and other
|
||||
/// vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged
|
||||
/// to route all communication over an HTTPS connection with pinning enabled.
|
||||
///
|
||||
/// - performDefaultEvaluation: Uses the default server trust evaluation while allowing you to control whether to
|
||||
/// validate the host provided by the challenge. Applications are encouraged to always
|
||||
/// validate the host in production environments to guarantee the validity of the server's
|
||||
/// certificate chain.
|
||||
///
|
||||
/// - disableEvaluation: Disables all evaluation which in turn will always consider any server trust as valid.
|
||||
///
|
||||
public enum ServerTrustPolicy {
|
||||
case performDefaultEvaluation(validateHost: Bool)
|
||||
case disableEvaluation
|
||||
|
||||
// MARK: - Evaluation
|
||||
/// Evaluates whether the server trust is valid.
|
||||
///
|
||||
/// - returns: Whether the server trust is valid.
|
||||
public func evaluate() -> Bool {
|
||||
var serverTrustIsValid = false
|
||||
|
||||
switch self {
|
||||
case .performDefaultEvaluation(_):
|
||||
break
|
||||
case .disableEvaluation:
|
||||
serverTrustIsValid = true
|
||||
}
|
||||
|
||||
return serverTrustIsValid
|
||||
}
|
||||
|
||||
/// Evaluates whether the server trust is valid for the given host.
|
||||
///
|
||||
/// - parameter serverTrust: The server trust to evaluate.
|
||||
/// - parameter host: The host of the challenge protection space.
|
||||
///
|
||||
/// - returns: Whether the server trust is valid.
|
||||
public func evaluate(_ serverTrust: SecTrust, forHost host: String) -> Bool {
|
||||
var serverTrustIsValid = false
|
||||
|
||||
switch self {
|
||||
case let .performDefaultEvaluation(validateHost):
|
||||
let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
|
||||
SecTrustSetPolicies(serverTrust, policy)
|
||||
case .disableEvaluation:
|
||||
serverTrustIsValid = true
|
||||
}
|
||||
|
||||
return serverTrustIsValid
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user