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:
T.Sasaki
2018-11-14 17:55:55 +09:00
parent 1fd724c3dc
commit 92f0970097
5 changed files with 109 additions and 18 deletions
+8
View File
@@ -132,6 +132,9 @@
79F5745B1DFDB10B00179ABF /* FileObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79F5745A1DFDB10A00179ABF /* FileObject.swift */; };
79F5745C1DFDB10B00179ABF /* FileObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79F5745A1DFDB10A00179ABF /* FileObject.swift */; };
79F5745D1DFDB10B00179ABF /* FileObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79F5745A1DFDB10A00179ABF /* FileObject.swift */; };
CE27C49B219BFFA0000BE23C /* ServerTrustPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE27C498219BFFA0000BE23C /* ServerTrustPolicy.swift */; };
CE27C49C219C041E000BE23C /* ServerTrustPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE27C498219BFFA0000BE23C /* ServerTrustPolicy.swift */; };
CE27C49D219C041E000BE23C /* ServerTrustPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE27C498219BFFA0000BE23C /* ServerTrustPolicy.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -206,6 +209,7 @@
79D903531FAB647400D61D31 /* FilesProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesProviderTests.swift; sourceTree = "<group>"; };
79D903551FAB647400D61D31 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
79F5745A1DFDB10A00179ABF /* FileObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileObject.swift; sourceTree = "<group>"; };
CE27C498219BFFA0000BE23C /* ServerTrustPolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServerTrustPolicy.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -352,6 +356,7 @@
798654321E8874BC002FA550 /* FTPHelper.swift */,
799396971D48C02300086753 /* SMBClient.swift */,
799396981D48C02300086753 /* SMBFileProvider.swift */,
CE27C498219BFFA0000BE23C /* ServerTrustPolicy.swift */,
);
path = Sources;
sourceTree = "<group>";
@@ -575,6 +580,7 @@
799396B31D48C02300086753 /* LocalFileProvider.swift in Sources */,
799396D41D48C02300086753 /* SMB2Tree.swift in Sources */,
7924B1A21D89DAE000589DB7 /* Options.swift in Sources */,
CE27C49D219C041E000BE23C /* ServerTrustPolicy.swift in Sources */,
792572411DF23BDA006A1526 /* LocalHelper.swift in Sources */,
7936BC121E880F5700A6C81C /* FTPFileProvider.swift in Sources */,
79480FF61E3ABDD0007E7275 /* CloudFileProvider.swift in Sources */,
@@ -619,6 +625,7 @@
799396B41D48C02300086753 /* LocalFileProvider.swift in Sources */,
799396D51D48C02300086753 /* SMB2Tree.swift in Sources */,
7924B1A31D89DAE000589DB7 /* Options.swift in Sources */,
CE27C49C219C041E000BE23C /* ServerTrustPolicy.swift in Sources */,
792572421DF23BDA006A1526 /* LocalHelper.swift in Sources */,
7936BC131E880F5700A6C81C /* FTPFileProvider.swift in Sources */,
79480FF71E3ABDD0007E7275 /* CloudFileProvider.swift in Sources */,
@@ -663,6 +670,7 @@
799396B51D48C02300086753 /* LocalFileProvider.swift in Sources */,
799396D61D48C02300086753 /* SMB2Tree.swift in Sources */,
7924B1A41D89DAE000589DB7 /* Options.swift in Sources */,
CE27C49B219BFFA0000BE23C /* ServerTrustPolicy.swift in Sources */,
792572431DF23BDA006A1526 /* LocalHelper.swift in Sources */,
7936BC141E880F5700A6C81C /* FTPFileProvider.swift in Sources */,
79480FF81E3ABDD0007E7275 /* CloudFileProvider.swift in Sources */,
+4 -4
View File
@@ -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()
}
+11 -11
View File
@@ -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)
+3 -3
View File
@@ -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()
+83
View File
@@ -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
}
}