forked from swift-server/security
/
TLSConfiguration.swift
191 lines (160 loc) · 8.58 KB
/
TLSConfiguration.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// This source file is part of the Swift.org Server APIs open source project
//
// Copyright (c) 2017 Swift Server API project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
//
import Foundation
// MARK: TLSConstants
///
/// A structure for storing TLS related constants
///
public struct TLSConstants {
// Max size of TLS record in Bytes
public static var maxTLSRecordLength: Int = 16384
}
// MARK: TLSConfiguration
///
/// A structure representing the configuration of an SSL/TLS connection
///
public struct TLSConfiguration {
// MARK: Properties
/// Certificates and keys are configured using a subset of the following properties
/// File name of CA certificate to be used.
public private(set) var caCertificateFilePath: String? = nil
/// Path to directory containing hashed CA's to be used.
/// *Note:* `caCertificateDirPath` - All certificates in the specified directory **must** be hashed.
public private(set) var caCertificateDirPath: String? = nil
/// Path to the certificate file to be used.
public private(set) var certificateFilePath: String? = nil
/// Path to the key file to be used.
public private(set) var keyFilePath: String? = nil
/// Path to the certificate chain file (optional).
public private(set) var certificateChainFilePath: String? = nil
/// Path to PEM formatted certificate string.
public private(set) var certificateString: String? = nil
/// True if server is using `self-signed` certificates.
public private(set) var certsAreSelfSigned = false
/// True if isServer == false and the client accepts self-signed certificates. Defaults to false, be careful to not leave as true in production
public private(set) var clientAllowsSelfSignedCertificates = false
#if os(Linux)
/// Cipher suites to use. Defaults to `DEFAULT`
public var cipherSuite: String = "DEFAULT"
#else
/// Cipher suites to use. Defaults to `14,13,2B,2F,2C,30,9E,9F,23,27,09,28,13,24,0A,14,67,33,6B,39,08,12,16,9C,9D,3C,3D,2F,35,0A`
// @FIXME: This isn't quite right, needs to be revisited.
public var cipherSuite: String = "14,13,2B,2F,2C,30,9E,9F,23,27,09,28,13,24,0A,14,67,33,6B,39,08,12,16,9C,9D,3C,3D,2F,35,0A"
/// `True` to use default cipher list, false otherwise.
public var useDefaultCiphers: Bool = true
/// Cached array of previously imported PKCS12.
public var pkcs12Certs: CFArray? = nil
#endif
/// Password (if needed) typically used for PKCS12 files.
public var password: String? = nil
/// True if no backing certificates provided (Readonly).
public private(set) var noBackingCertificates = false
// MARK: Lifecycle
///
/// Initialize a configuration using a `CA Certificate` file.
///
/// - Parameters:
/// - caCertificateFilePath: Path to the PEM formatted CA certificate file.
/// - certificateFilePath: Path to the PEM formatted certificate file.
/// - keyFilePath: Path to the PEM formatted key file. If nil, `certificateFilePath` will be used.
/// - selfSigned: True if certs are `self-signed`, false otherwise. Defaults to true.
/// - cipherSuite: Optional String containing the cipher suite to use.
///
/// - Returns: New Configuration instance.
///
public init(withCACertificateFilePath caCertificateFilePath: String?, usingCertificateFile certificateFilePath: String?, withKeyFile keyFilePath: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil) {
self.certificateFilePath = certificateFilePath
self.keyFilePath = keyFilePath ?? certificateFilePath
self.certsAreSelfSigned = selfSigned
self.caCertificateFilePath = caCertificateFilePath
if cipherSuite != nil {
self.cipherSuite = cipherSuite!
}
}
///
/// Initialize a configuration using a `CA Certificate` directory.
///
/// *Note:* `caCertificateDirPath` - All certificates in the specified directory **must** be hashed using the `OpenSSL Certificate Tool`.
///
/// - Parameters:
/// - caCertificateDirPath: Path to a directory containing CA certificates. *(see note above)*
/// - certificateFilePath: Path to the PEM formatted certificate file. If nil, `certificateFilePath` will be used.
/// - keyFilePath: Path to the PEM formatted key file (optional). If nil, `certificateFilePath` is used.
/// - selfSigned: True if certs are `self-signed`, false otherwise. Defaults to true.
/// - cipherSuite: Optional String containing the cipher suite to use.
///
/// - Returns: New Configuration instance.
///
public init(withCACertificateDirectory caCertificateDirPath: String?, usingCertificateFile certificateFilePath: String?, withKeyFile keyFilePath: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil) {
self.certificateFilePath = certificateFilePath
self.keyFilePath = keyFilePath ?? certificateFilePath
self.certsAreSelfSigned = selfSigned
self.caCertificateDirPath = caCertificateDirPath
if cipherSuite != nil {
self.cipherSuite = cipherSuite!
}
}
///
/// Initialize a configuration using a `Certificate Chain File`.
///
/// *Note:* If using a certificate chain file, the certificates must be in PEM format and must be sorted starting with the subject's certificate (actual client or server certificate), followed by intermediate CA certificates if applicable, and ending at the highest level (root) CA.
///
/// - Parameters:
/// - chainFilePath: Path to the certificate chain file (optional). *(see note above)*
/// - password: Password for the chain file (optional).
/// - selfSigned: True if certs are `self-signed`, false otherwise. Defaults to true.
/// - clientAllowsSelfSignedCertificates: True if, as a client, connections to self-signed servers are allowed
/// - cipherSuite: Optional String containing the cipher suite to use.
///
/// - Returns: New Configuration instance.
///
public init(withChainFilePath chainFilePath: String? = nil, withPassword password: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, clientAllowsSelfSignedCertificates: Bool = false, cipherSuite: String? = nil) {
self.certificateChainFilePath = chainFilePath
self.password = password
self.certsAreSelfSigned = selfSigned
self.clientAllowsSelfSignedCertificates = clientAllowsSelfSignedCertificates
if cipherSuite != nil {
self.cipherSuite = cipherSuite!
}
}
#if os(Linux)
///
/// Initialize a configuration using a `PEM formatted certificate in String form`.
///
/// - Parameters:
/// - certificateString: PEM formatted certificate in String form.
/// - selfSigned: True if certs are `self-signed`, false otherwise. Defaults to true.
/// - cipherSuite: Optional String containing the cipher suite to use.
///
/// - Returns: New Configuration instance.
///
public init(withPEMCertificateString certificateString: String, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil) {
self.certificateString = certificateString
self.certsAreSelfSigned = selfSigned
if cipherSuite != nil {
self.cipherSuite = cipherSuite!
}
}
#endif
///
/// Initialize a configuration with no backing certificates.
///
/// - Parameters:
/// - clientAllowsSelfSignedCertificates: True if, as a client, connections to self-signed servers are allowed
/// - cipherSuite: Optional String containing the cipher suite to use.
///
/// - Returns: New Configuration instance.
///
public init(clientAllowsSelfSignedCertificates: Bool = false, withCipherSuite cipherSuite: String?) {
self.noBackingCertificates = true
self.clientAllowsSelfSignedCertificates = clientAllowsSelfSignedCertificates
if cipherSuite != nil {
self.cipherSuite = cipherSuite!
}
}
}