diff options
| author | Steven Fackler <[email protected]> | 2018-02-25 23:04:54 -0800 |
|---|---|---|
| committer | Steven Fackler <[email protected]> | 2018-02-25 23:20:10 -0800 |
| commit | b7ba5773396fb4ba7fb1ff5d770b5b2632adc471 (patch) | |
| tree | 49bb99da6ca79f3f9973c2ff2f373157dbc9e8a4 /openssl/src | |
| parent | Restore error stack in cookie callback (diff) | |
| download | rust-openssl-b7ba5773396fb4ba7fb1ff5d770b5b2632adc471.tar.xz rust-openssl-b7ba5773396fb4ba7fb1ff5d770b5b2632adc471.zip | |
Add min/max protocol version support
Diffstat (limited to 'openssl/src')
| -rw-r--r-- | openssl/src/ssl/mod.rs | 104 | ||||
| -rw-r--r-- | openssl/src/ssl/test.rs | 33 |
2 files changed, 133 insertions, 4 deletions
diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 91b97818..1ae480c5 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1007,6 +1007,11 @@ impl SslContextBuilder { /// /// This corresponds to [`SSL_CTX_set_options`]. /// + /// # Note + /// + /// This *enables* the specified options, but does not disable unspecified options. Use + /// `clear_options` for that. + /// /// [`SSL_CTX_set_options`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_options.html pub fn set_options(&mut self, option: SslOptions) -> SslOptions { let bits = unsafe { compat::SSL_CTX_set_options(self.as_ptr(), option.bits()) }; @@ -1033,6 +1038,90 @@ impl SslContextBuilder { SslOptions { bits } } + /// Sets the minimum supported protocol version. + /// + /// A value of `None` will enable protocol versions down the the lowest version supported by + /// OpenSSL. + /// + /// This corresponds to [`SSL_CTX_set_min_proto_version`]. + /// + /// Requires OpenSSL 1.1.0 or 1.1.1 and the corresponding Cargo feature. + /// + /// [`SSL_CTX_set_min_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html + #[cfg(any(all(feature = "v110", ossl110), all(feature = "v111", ossl111)))] + pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::SSL_CTX_set_min_proto_version( + self.as_ptr(), + version.map_or(0, |v| v.0), + )).map(|_| ()) + } + } + + /// Sets the maximum supported protocol version. + /// + /// A value of `None` will enable protocol versions down the the highest version supported by + /// OpenSSL. + /// + /// This corresponds to [`SSL_CTX_set_max_proto_version`]. + /// + /// Requires OpenSSL 1.1.0 or 1.1.1 and the corresponding Cargo feature. + /// + /// [`SSL_CTX_set_max_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html + #[cfg(any(all(feature = "v110", ossl110), all(feature = "v111", ossl111)))] + pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::SSL_CTX_set_max_proto_version( + self.as_ptr(), + version.map_or(0, |v| v.0), + )).map(|_| ()) + } + } + + /// Gets the minimum supported protocol version. + /// + /// A value of `None` indicates that all versions down the the lowest version supported by + /// OpenSSL are enabled. + /// + /// This corresponds to [`SSL_CTX_get_min_proto_version`]. + /// + /// Requires OpenSSL 1.1.0 or 1.1.1 and the corresponding Cargo feature. + /// + /// [`SSL_CTX_get_min_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html + #[cfg(any(all(feature = "v110", ossl110), all(feature = "v111", ossl111)))] + pub fn min_proto_version(&mut self) -> Option<SslVersion> { + unsafe { + let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr()); + if r == 0 { + None + } else { + Some(SslVersion(r)) + } + } + } + + /// Gets the maximum supported protocol version. + /// + /// A value of `None` indicates that all versions down the the highest version supported by + /// OpenSSL are enabled. + /// + /// This corresponds to [`SSL_CTX_get_max_proto_version`]. + /// + /// Requires OpenSSL 1.1.0 or 1.1.1 and the corresponding Cargo feature. + /// + /// [`SSL_CTX_get_max_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html + #[cfg(any(all(feature = "v110", ossl110), all(feature = "v111", ossl111)))] + pub fn max_proto_version(&mut self) -> Option<SslVersion> { + unsafe { + let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr()); + if r == 0 { + None + } else { + Some(SslVersion(r)) + } + } + } + /// Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN). /// /// The input must be in ALPN "wire format". It consists of a sequence of supported protocol @@ -1319,7 +1408,7 @@ impl SslContextBuilder { /// This corresponds to `SSL_CTX_set_cookie_generate_cb`. pub fn set_cookie_generate_cb<F>(&mut self, callback: F) where - F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send + F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, { unsafe { let callback = Box::new(callback); @@ -1343,7 +1432,7 @@ impl SslContextBuilder { /// This corresponds to `SSL_CTX_set_cookie_verify_cb`. pub fn set_cookie_verify_cb<F>(&mut self, callback: F) where - F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send + F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, { unsafe { let callback = Box::new(callback); @@ -2011,8 +2100,15 @@ impl SslRef { /// This corresponds to [`SSL_version`]. /// /// [`SSL_version`]: https://www.openssl.org/docs/manmaster/man3/SSL_version.html - pub fn version2(&self) -> SslVersion { - unsafe { SslVersion(ffi::SSL_version(self.as_ptr())) } + pub fn version2(&self) -> Option<SslVersion> { + unsafe { + let r = ffi::SSL_version(self.as_ptr()); + if r == 0 { + None + } else { + Some(SslVersion(r)) + } + } } /// Returns a string describing the protocol version of the session. diff --git a/openssl/src/ssl/test.rs b/openssl/src/ssl/test.rs index b8e9b8c2..ae8c12de 100644 --- a/openssl/src/ssl/test.rs +++ b/openssl/src/ssl/test.rs @@ -20,6 +20,8 @@ use ocsp::{OcspResponse, OcspResponseStatus}; use ssl; use ssl::{Error, HandshakeError, ShutdownResult, Ssl, SslAcceptor, SslConnector, SslContext, SslFiletype, SslMethod, SslSessionCacheMode, SslStream, SslVerifyMode, StatusType}; +#[cfg(any(all(feature = "v110", ossl110), all(feature = "v111", ossl111)))] +use ssl::SslVersion; use x509::{X509, X509Name, X509StoreContext, X509VerifyResult}; #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110), all(feature = "v111", ossl111)))] @@ -1320,6 +1322,37 @@ fn keying_export() { assert_eq!(buf, buf2); } +#[test] +#[cfg(any(all(feature = "v110", ossl110), all(feature = "v111", ossl111)))] +fn no_version_overlap() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = listener.local_addr().unwrap(); + + let guard = thread::spawn(move || { + let stream = listener.accept().unwrap().0; + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_certificate_file(&Path::new("test/cert.pem"), SslFiletype::PEM) + .unwrap(); + ctx.set_private_key_file(&Path::new("test/key.pem"), SslFiletype::PEM) + .unwrap(); + ctx.set_max_proto_version(Some(SslVersion::TLS1_1)).unwrap(); + assert_eq!(ctx.min_proto_version(), None); + assert_eq!(ctx.max_proto_version(), Some(SslVersion::TLS1_1)); + let ssl = Ssl::new(&ctx.build()).unwrap(); + ssl.accept(stream).unwrap_err(); + }); + + let stream = TcpStream::connect(addr).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_min_proto_version(Some(SslVersion::TLS1_2)).unwrap(); + assert_eq!(ctx.min_proto_version(), Some(SslVersion::TLS1_2)); + assert_eq!(ctx.max_proto_version(), None); + let ssl = Ssl::new(&ctx.build()).unwrap(); + ssl.connect(stream).unwrap_err(); + + guard.join().unwrap(); +} + fn _check_kinds() { fn is_send<T: Send>() {} fn is_sync<T: Sync>() {} |