Merge pull request #853 from sfackler/min-max-version
Add min/max protocol version support
This commit is contained in:
commit
42ec251b55
|
|
@ -33,9 +33,10 @@ pub enum X509_ALGOR {}
|
|||
pub enum X509_VERIFY_PARAM {}
|
||||
pub enum X509_REQ {}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub type SSL_CTX_keylog_cb_func =
|
||||
Option<unsafe extern "C" fn(ssl: *const SSL, line: *const c_char)>;
|
||||
pub const SSL_CTRL_SET_MIN_PROTO_VERSION: c_int = 123;
|
||||
pub const SSL_CTRL_SET_MAX_PROTO_VERSION: c_int = 124;
|
||||
pub const SSL_CTRL_GET_MIN_PROTO_VERSION: c_int = 130;
|
||||
pub const SSL_CTRL_GET_MAX_PROTO_VERSION: c_int = 131;
|
||||
|
||||
pub const SSL_OP_MICROSOFT_SESS_ID_BUG: c_ulong = 0x00000000;
|
||||
pub const SSL_OP_NETSCAPE_CHALLENGE_BUG: c_ulong = 0x00000000;
|
||||
|
|
@ -48,9 +49,6 @@ pub const SSL_OP_SINGLE_ECDH_USE: c_ulong = 0x00000000;
|
|||
pub const SSL_OP_SINGLE_DH_USE: c_ulong = 0x00000000;
|
||||
pub const SSL_OP_NO_SSLv2: c_ulong = 0x00000000;
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub const TLS1_3_VERSION: c_int = 0x304;
|
||||
|
||||
pub const OPENSSL_VERSION: c_int = 0;
|
||||
pub const OPENSSL_CFLAGS: c_int = 1;
|
||||
pub const OPENSSL_BUILT_ON: c_int = 2;
|
||||
|
|
@ -81,6 +79,58 @@ pub fn init() {
|
|||
})
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_CTX_set_min_proto_version(ctx: *mut ::SSL_CTX, version: c_int) -> c_int {
|
||||
::SSL_CTX_ctrl(
|
||||
ctx,
|
||||
SSL_CTRL_SET_MIN_PROTO_VERSION,
|
||||
version as c_long,
|
||||
ptr::null_mut(),
|
||||
) as c_int
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_CTX_set_max_proto_version(ctx: *mut ::SSL_CTX, version: c_int) -> c_int {
|
||||
::SSL_CTX_ctrl(
|
||||
ctx,
|
||||
SSL_CTRL_SET_MAX_PROTO_VERSION,
|
||||
version as c_long,
|
||||
ptr::null_mut(),
|
||||
) as c_int
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_CTX_get_min_proto_version(ctx: *mut ::SSL_CTX) -> c_int {
|
||||
::SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, ptr::null_mut()) as c_int
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_CTX_get_max_proto_version(ctx: *mut ::SSL_CTX) -> c_int {
|
||||
::SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, ptr::null_mut()) as c_int
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_set_min_proto_version(s: *mut ::SSL, version: c_int) -> c_int {
|
||||
::SSL_ctrl(
|
||||
s,
|
||||
SSL_CTRL_SET_MIN_PROTO_VERSION,
|
||||
version as c_long,
|
||||
ptr::null_mut(),
|
||||
) as c_int
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_set_max_proto_version(s: *mut ::SSL, version: c_int) -> c_int {
|
||||
::SSL_ctrl(
|
||||
s,
|
||||
SSL_CTRL_SET_MAX_PROTO_VERSION,
|
||||
version as c_long,
|
||||
ptr::null_mut(),
|
||||
) as c_int
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_get_min_proto_version(s: *mut ::SSL) -> c_int {
|
||||
::SSL_ctrl(s, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, ptr::null_mut()) as c_int
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_get_max_proto_version(s: *mut ::SSL) -> c_int {
|
||||
::SSL_ctrl(s, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, ptr::null_mut()) as c_int
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn BIO_new(type_: *const BIO_METHOD) -> *mut BIO;
|
||||
pub fn BIO_s_file() -> *const BIO_METHOD;
|
||||
|
|
@ -221,8 +271,6 @@ extern "C" {
|
|||
);
|
||||
pub fn SSL_get_client_random(ssl: *const SSL, out: *mut c_uchar, len: size_t) -> size_t;
|
||||
pub fn SSL_get_server_random(ssl: *const SSL, out: *mut c_uchar, len: size_t) -> size_t;
|
||||
#[cfg(ossl111)]
|
||||
pub fn SSL_CTX_set_keylog_callback(ctx: *mut ::SSL_CTX, cb: SSL_CTX_keylog_cb_func);
|
||||
pub fn X509_getm_notAfter(x: *const ::X509) -> *mut ::ASN1_TIME;
|
||||
pub fn X509_getm_notBefore(x: *const ::X509) -> *mut ::ASN1_TIME;
|
||||
pub fn X509_get0_signature(
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
use libc::{c_int, c_ulong};
|
||||
use libc::{c_char, c_int, c_ulong};
|
||||
|
||||
use ossl110::*;
|
||||
pub type SSL_CTX_keylog_cb_func =
|
||||
Option<unsafe extern "C" fn(ssl: *const ::SSL, line: *const c_char)>;
|
||||
|
||||
pub const SSL_COOKIE_LENGTH: c_int = 255;
|
||||
|
||||
pub const SSL_OP_ENABLE_MIDDLEBOX_COMPAT: c_ulong = 0x00100000;
|
||||
|
||||
pub const TLS1_3_VERSION: c_int = 0x304;
|
||||
|
||||
extern "C" {
|
||||
pub fn SSL_stateless(s: *mut SSL) -> c_int;
|
||||
pub fn SSL_CTX_set_keylog_callback(ctx: *mut ::SSL_CTX, cb: SSL_CTX_keylog_cb_func);
|
||||
pub fn SSL_stateless(s: *mut ::SSL) -> c_int;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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>() {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue