From dd731efa48482c90a4335fe238f25d187e57d0cf Mon Sep 17 00:00:00 2001 From: Ritesh Khadgaray Date: Tue, 2 Jun 2020 14:34:34 -0700 Subject: [PATCH] add support for ssl proxy - update docker image to ubuntu 16.04 - add support for ssl proxy --- Cargo.toml | 6 ++++++ ci/Dockerfile-linux64-curl | 2 +- curl-sys/lib.rs | 3 +++ examples/ssl_proxy.rs | 29 +++++++++++++++++++++++++++++ src/easy/handle.rs | 15 +++++++++++++++ src/easy/handler.rs | 24 ++++++++++++++++++++++++ systest/build.rs | 5 ++++- 7 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 examples/ssl_proxy.rs diff --git a/Cargo.toml b/Cargo.toml index 4c6c8e3203..6f59c57017 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ winapi = { version = '0.3', features = ['libloaderapi', 'wincrypt'] } [dev-dependencies] mio = "0.6" mio-extras = "2.0.3" +anyhow = "1.0.31" [workspace] members = ["systest"] @@ -49,3 +50,8 @@ protocol-ftp = ["curl-sys/protocol-ftp"] [[test]] name = "atexit" harness = false + +[[example]] +name = "ssl_proxy" +path = "examples/ssl_proxy.rs" +required-features = ["ssl"] diff --git a/ci/Dockerfile-linux64-curl b/ci/Dockerfile-linux64-curl index be03c24daf..dd58df1363 100644 --- a/ci/Dockerfile-linux64-curl +++ b/ci/Dockerfile-linux64-curl @@ -1,4 +1,4 @@ -FROM ubuntu:14.04 +FROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y --no-install-recommends \ diff --git a/curl-sys/lib.rs b/curl-sys/lib.rs index 0049a9d135..90aede1cdd 100644 --- a/curl-sys/lib.rs +++ b/curl-sys/lib.rs @@ -576,6 +576,9 @@ pub const CURLOPT_SSL_OPTIONS: CURLoption = CURLOPTTYPE_LONG + 216; // pub const CURLOPT_LOGIN_OPTIONS: CURLoption = CURLOPTTYPE_OBJECTPOINT + 224; pub const CURLOPT_UNIX_SOCKET_PATH: CURLoption = CURLOPTTYPE_OBJECTPOINT + 231; pub const CURLOPT_PIPEWAIT: CURLoption = CURLOPTTYPE_LONG + 237; +pub const CURLOPT_PROXY_CAINFO: CURLoption = CURLOPTTYPE_OBJECTPOINT + 246; +pub const CURLOPT_PROXY_SSLCERT: CURLoption = CURLOPTTYPE_OBJECTPOINT + 254; +pub const CURLOPT_PROXY_SSLKEY: CURLoption = CURLOPTTYPE_OBJECTPOINT + 256; pub const CURL_IPRESOLVE_WHATEVER: c_int = 0; pub const CURL_IPRESOLVE_V4: c_int = 1; diff --git a/examples/ssl_proxy.rs b/examples/ssl_proxy.rs new file mode 100644 index 0000000000..9ab6f823cf --- /dev/null +++ b/examples/ssl_proxy.rs @@ -0,0 +1,29 @@ +extern crate anyhow; + +use anyhow::Result; + +fn main() -> Result<()> { + let mut handle = curl::easy::Easy::new(); + + let proxy_url = "https://fwdproxy"; + let proxy_port = 8082; + let cainfo = "/var/credentials/root/ca.pem"; + let sslcert = "/var/credentials/user/x509.pem"; + let sslkey = "/var/credentials/user/x509.pem"; + + handle.connect_timeout(std::time::Duration::from_secs(5))?; + handle.connect_only(true)?; + handle.verbose(true)?; + handle.url("https://www.google.com")?; + + handle.proxy(proxy_url)?; + handle.proxy_port(proxy_port)?; + handle.proxy_cainfo(&cainfo)?; + handle.proxy_sslcert(&sslcert)?; + handle.proxy_sslkey(&sslkey)?; + println!("ssl proxy setup done"); + + handle.perform()?; + println!("connected done"); + Ok(()) +} diff --git a/src/easy/handle.rs b/src/easy/handle.rs index 3152bb39c0..ef2f1bb886 100644 --- a/src/easy/handle.rs +++ b/src/easy/handle.rs @@ -563,6 +563,21 @@ impl Easy { self.inner.proxy_port(port) } + /// Same as [`Easy2::proxy_cainfo`](struct.Easy2.html#method.proxy_cainfo) + pub fn proxy_cainfo(&mut self, cainfo: &str) -> Result<(), Error> { + self.inner.proxy_cainfo(cainfo) + } + + /// Same as [`Easy2::proxy_sslcert`](struct.Easy2.html#method.proxy_sslcert) + pub fn proxy_sslcert(&mut self, sslcert: &str) -> Result<(), Error> { + self.inner.proxy_sslcert(sslcert) + } + + /// Same as [`Easy2::proxy_sslkey`](struct.Easy2.html#method.proxy_sslkey) + pub fn proxy_sslkey(&mut self, sslkey: &str) -> Result<(), Error> { + self.inner.proxy_sslkey(sslkey) + } + /// Same as [`Easy2::proxy_type`](struct.Easy2.html#method.proxy_type) pub fn proxy_type(&mut self, kind: ProxyType) -> Result<(), Error> { self.inner.proxy_type(kind) diff --git a/src/easy/handler.rs b/src/easy/handler.rs index f6c4e02818..6564ec8fd2 100644 --- a/src/easy/handler.rs +++ b/src/easy/handler.rs @@ -881,6 +881,30 @@ impl Easy2 { self.setopt_long(curl_sys::CURLOPT_PROXYPORT, port as c_long) } + /// Set CA certificate to verify peer against for proxy + /// + /// By default this value is not set and corresponds to `CURLOPT_PROXY_CAINFO`. + pub fn proxy_cainfo(&mut self, cainfo: &str) -> Result<(), Error> { + let cainfo = CString::new(cainfo)?; + self.setopt_str(curl_sys::CURLOPT_PROXY_CAINFO, &cainfo) + } + + /// Set client certificate for proxy + /// + /// By default this value is not set and corresponds to `CURLOPT_PROXY_SSLCERT`. + pub fn proxy_sslcert(&mut self, sslcert: &str) -> Result<(), Error> { + let sslcert = CString::new(sslcert)?; + self.setopt_str(curl_sys::CURLOPT_PROXY_SSLCERT, &sslcert) + } + + /// Set private key for HTTPS proxy + /// + /// By default this value is not set and corresponds to `CURLOPT_PROXY_SSLKEY`. + pub fn proxy_sslkey(&mut self, sslkey: &str) -> Result<(), Error> { + let sslkey = CString::new(sslkey)?; + self.setopt_str(curl_sys::CURLOPT_PROXY_SSLKEY, &sslkey) + } + /// Indicates the type of proxy being used. /// /// By default this option is `ProxyType::Http` and corresponds to diff --git a/systest/build.rs b/systest/build.rs index 151b52c9e9..f53e190fc9 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -109,7 +109,10 @@ fn main() { } if version < 54 { match s { - "CURL_SSLVERSION_TLSv1_3" => return true, + "CURL_SSLVERSION_TLSv1_3" + | "CURLOPT_PROXY_CAINFO" + | "CURLOPT_PROXY_SSLCERT" + | "CURLOPT_PROXY_SSLKEY" => return true, _ => {} } }