From f35f6c41b0774494182d7aa446141a3463e45cc2 Mon Sep 17 00:00:00 2001 From: Zsolt Varadi Date: Wed, 18 Dec 2019 22:24:25 +0100 Subject: [PATCH] Expose SSL options via CurlyOption --- README.md | 44 +++++++++++++++-- Sources/CurlyClient/CurlyOption+Private.swift | 49 +++++++++++++++++++ Sources/CurlyClient/CurlyOption.swift | 46 +++++++++++++++++ 3 files changed, 135 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 678dcc7..fb84624 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ let package = Package( dependencies: [ // 💧 A server-side Swift web framework. .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"), - .package(url: "https://github.com/vzsg/Curly.git", from: "0.4.0"), + .package(url: "https://github.com/vzsg/Curly.git", from: "0.6.0"), // ... other dependencies ... ], targets: [ @@ -66,6 +66,10 @@ See the tests for examples of both methods. Equivalent to the [`-U`/`--proxy-user`](https://curl.haxx.se/docs/manpage.html#-U) parameter of curl, which allows specifying the username and password to use when authenticating to the proxy server. +- **proxyPort(Int)** (New in 0.6.0) + + Equivalent to `CURLOPT_PROXYPORT`, which allows separately overriding the port used to connect to the proxy. + - **timeout(Int)** Equivalent to the [`-m`/`--max-time`](https://curl.haxx.se/docs/manpage.html#-m) parameter of curl, which allows specifying the maximum time allowed to service the request in seconds. @@ -83,8 +87,8 @@ See the tests for examples of both methods. Same as `connectTimeout`, but with milliseconds precision. - **cookieJar(String)** - - Equivalent to the **both** the [`-b`/`--cookie`](ttps://curl.haxx.se/docs/manpage.html#-b) **and** [`-c`/`--cookie-jar`](ttps://curl.haxx.se/docs/manpage.html#-c) parameters of curl. The file name provided with the option will be used as a cookie storage – reading and writing – for this request. See the tests for an example. + + Equivalent to setting **both** the [`-b`/`--cookie`](https://curl.haxx.se/docs/manpage.html#-b) **and** [`-c`/`--cookie-jar`](https://curl.haxx.se/docs/manpage.html#-c) parameters of curl. The file name provided with the option will be used as a cookie storage – reading and writing – for this request. See the tests for an example. - **followRedirects(Bool)** @@ -92,4 +96,36 @@ See the tests for examples of both methods. - **insecure(Bool)** - Equivalent to the [`-k`/`--insecure`](https://curl.haxx.se/docs/manpage.html#-k) parameter of curl, which can disable verification of the certificates received from the remote server. + Equivalent to the [`-k`/`--insecure`](https://curl.haxx.se/docs/manpage.html#-k) parameter of curl, which can disable verification of the certificates received from the remote server. Deprecated in favor of `sslVerifyPeer`. + +- **sslVerifyPeer(Bool)** (New in 0.6.0) + + Equivalent to [`CURLOPT_SSL_VERIFYPEER`](https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html]), used to enable or disable server certificate verification. + +- **sslVerifyHost(Bool)** (New in 0.6.0) + + Equivalent to [`CURLOPT_SSL_VERIFYHOST`](https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html]), used to enable or disable verification of the server host name against the server certificates. + +- **sslKey(path: String, type: CurlySSLFileType?, password: String?)** (New in 0.6.0) + + Equivalent to the [`--key`](https://curl.haxx.se/docs/manpage.html#--key), [`--key-type`](https://curl.haxx.se/docs/manpage.html#--key-type) and [`--pass`](https://curl.haxx.se/docs/manpage.html#--pass) parameters, used to specify a private key to use for client certificate verification. + +- **sslCert(path: String, type: CurlySSLFileType?)** (New in 0.6.0) + + Equivalent to the [`--cert`](https://curl.haxx.se/docs/manpage.html#--cert) and [`--cert-type`](https://curl.haxx.se/docs/manpage.html#--cert-type) parameters, used to specify a client certificate. + +- **sslCAFilePath(String)** (New in 0.6.0) + + Equivalent to the [`--cacert`](https://curl.haxx.se/docs/manpage.html#--cacert) parameter, used to specify a certificate to verify the server certificates against. + +- **sslCADirPath(String)** (New in 0.6.0) + + Equivalent to the [`--cadir`](https://curl.haxx.se/docs/manpage.html#--cadir) parameter, used to specify a folder containing certificates to verify the server certificates against. + +- **sslCiphers([String])** (New in 0.6.0) + + Equivalent to the [`--ciphers`](https://curl.haxx.se/docs/manpage.html#--ciphers) parameter, used to specify which ciphers to allow. See [this page](https://curl.haxx.se/docs/ssl-ciphers.html) for details. + +- **sslPinnedPublicKey(String)** (New in 0.6.0) + + Equivalent to the [`--pinnedpubkey`](https://curl.haxx.se/docs/manpage.html#--pinnedpubkey) parameter, used to specify either a file with a PEM/DER encoded public key, or an SHA-256 hash that the server must present in its certificate chain. diff --git a/Sources/CurlyClient/CurlyOption+Private.swift b/Sources/CurlyClient/CurlyOption+Private.swift index 398d002..ac4858a 100644 --- a/Sources/CurlyClient/CurlyOption+Private.swift +++ b/Sources/CurlyClient/CurlyOption+Private.swift @@ -33,6 +33,55 @@ extension CurlyOption { return [.followLocation(follow)] case .insecure(let insecure): return [CURLRequest.Option.sslVerifyPeer(!insecure)] + case .proxyPort(let port): + return [.proxyPort(port)] + case .sslVerifyPeer(let verify): + return [.sslVerifyPeer(verify)] + case .sslVerifyHost(let verify): + return [.sslVerifyHost(verify)] + case .sslKey(let path, let type, let password): + var options: [CURLRequest.Option] = [.sslKey(path)] + + if let type = type { + options.append(.sslKeyType(type.curlType)) + } + + if let password = password { + options.append(.sslKeyPwd(password)) + } + + return options + case .sslCert(let path, let type): + var options: [CURLRequest.Option] = [.sslCert(path)] + + if let type = type { + options.append(.sslCertType(type.curlType)) + } + + return options + case .sslCAFilePath(let path): + return [.sslCAFilePath(path)] + case .sslCADirPath(let path): + return [.sslCADirPath(path)] + case .sslCiphers(let ciphers): + return [.sslCiphers(ciphers)] + case .sslPinnedPublicKey(let key): + return [.sslPinnedPublicKey(key)] + } + } +} + +private extension CurlySSLFileType { + var curlType: CURLRequest.SSLFileType { + switch self { + case .der: + return .der + case .eng: + return .eng + case .p12: + return .p12 + case .pem: + return .pem } } } diff --git a/Sources/CurlyClient/CurlyOption.swift b/Sources/CurlyClient/CurlyOption.swift index 48ec797..a4b721d 100644 --- a/Sources/CurlyClient/CurlyOption.swift +++ b/Sources/CurlyClient/CurlyOption.swift @@ -1,15 +1,61 @@ import Vapor public enum CurlyOption { + /// Proxy server address. case proxy(String) + /// Proxy server username/password combination. case proxyAuth(user: String, password: String) + /// Port override for the proxy server. + case proxyPort(Int) + /// Maximum time in seconds for the request to complete. + /// The default timeout is never. case timeout(Int) + /// Maximum time in milliseconds for the request to complete. + /// The default timeout is never. case timeoutMs(Int) + /// Maximum time in seconds for the request connection phase. + /// The default timeout is 300 seconds. case connectTimeout(Int) + /// Maximum time in milliseconds for the request connection phase. + /// The default timeout is 300 seconds. case connectTimeoutMs(Int) + /// The name of the file from which cookies will be read before, + /// and written to after performing the HTTP request. case cookieJar(String) + /// Indicates that the request should follow redirects. Default is false. case followRedirects(Bool) + + /// Indicates whether the request should skip verification of the authenticity of the peer's certificate. Defaults to false. + /// Deprecated, use .sslVerifyPeer(false) instead. + @available(*, deprecated, message: "Use the sslVerifyPeer and other SSL options instead.") case insecure(Bool) + + /// Indicates whether the request should verify the authenticity of the peer's certificate. Defaults to true. + case sslVerifyPeer(Bool) + /// Indicates whether the request should verify that the server cert is for the hostname of the server. Defaults to true. + case sslVerifyHost(Bool) + /// Path, optional type (defaults to PEM) and optional passphrase (defaults to none) for a client private key file. + case sslKey(path: String, type: CurlySSLFileType?, password: String?) + /// Path and optional type (defaults to PEM) for a client certificate. + case sslCert(path: String, type: CurlySSLFileType?) + /// Path to file holding one or more certificates which will be used to verify the peer. + case sslCAFilePath(String) + /// Path to directory holding one or more certificates which will be used to verify the peer. + case sslCADirPath(String) + /// Override the list of ciphers to use for the SSL connection. + /// Consists of one or more cipher strings separated by colons. Commas or spaces are also acceptable + /// separators but colons are normally used. "!", "-" and "+" can be used as operators. + case sslCiphers([String]) + /// File path to the pinned key. + /// When negotiating a TLS or SSL connection, the server sends a certificate indicating its + /// identity. A key is extracted from this certificate and if it does not exactly + /// match the key provided to this option, curl will abort the connection before + /// sending or receiving any data. + case sslPinnedPublicKey(String) +} + +public enum CurlySSLFileType { + case pem, der, p12, eng } extension Request {