aboutsummaryrefslogtreecommitdiff
path: root/openssl/src
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2018-02-25 23:04:54 -0800
committerSteven Fackler <[email protected]>2018-02-25 23:20:10 -0800
commitb7ba5773396fb4ba7fb1ff5d770b5b2632adc471 (patch)
tree49bb99da6ca79f3f9973c2ff2f373157dbc9e8a4 /openssl/src
parentRestore error stack in cookie callback (diff)
downloadrust-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.rs104
-rw-r--r--openssl/src/ssl/test.rs33
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>() {}