Commit a43011d7 authored by Manuel Schölling's avatar Manuel Schölling
Browse files

Fix probelms with DTLS when no packets are pending.

When using DTLS you might run into the situation where no packets
are pending, so SSL_read returns len=0. On a TLS connection this
means that the connection was closed, but on DTLS it does not
(a DTLS connection cannot be closed in the usual sense).
This commit fixes a bug introduced by c8d23f37.

Conflicts:
	openssl/src/ssl/mod.rs
parent 2e0ae7a8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -525,6 +525,7 @@ extern "C" {
    pub fn SSL_get_SSL_CTX(ssl: *mut SSL) -> *mut SSL_CTX;
    pub fn SSL_get_current_compression(ssl: *mut SSL) -> *const COMP_METHOD;
    pub fn SSL_get_peer_certificate(ssl: *mut SSL) -> *mut X509;
    pub fn SSL_get_ssl_method(ssl: *mut SSL) -> *const SSL_METHOD;

    pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char;

+35 −1
Original line number Diff line number Diff line
@@ -141,6 +141,25 @@ impl SslMethod {
        }
    }

    unsafe fn from_raw(method: *const ffi::SSL_METHOD) -> Option<SslMethod> {
        match method {
            #[cfg(feature = "sslv2")]
            x if x == ffi::SSLv2_method() => Some(SslMethod::Sslv2),
            x if x == ffi::SSLv3_method() => Some(SslMethod::Sslv3),
            x if x == ffi::TLSv1_method() => Some(SslMethod::Tlsv1),
            x if x == ffi::SSLv23_method() => Some(SslMethod::Sslv23),
            #[cfg(feature = "tlsv1_1")]
            x if x == ffi::TLSv1_1_method() => Some(SslMethod::Tlsv1_1),
            #[cfg(feature = "tlsv1_2")]
            x if x == ffi::TLSv1_2_method() => Some(SslMethod::Tlsv1_2),
            #[cfg(feature = "dtlsv1")]
            x if x == ffi::DTLSv1_method() => Some(SslMethod::Dtlsv1),
            #[cfg(feature = "dtlsv1_2")]
            x if x == ffi::DTLSv1_2_method() => Some(SslMethod::Dtlsv1_2),
            _ => None,
        }
    }

    #[cfg(feature = "dtlsv1")]
    pub fn is_dtlsv1(&self) -> bool {
        *self == SslMethod::Dtlsv1
@@ -787,6 +806,13 @@ impl Ssl {
            ffi::SSL_pending(self.ssl) as usize
        }
    }

    pub fn get_ssl_method(&self) -> Option<SslMethod> {
        unsafe {
            let method = ffi::SSL_get_ssl_method(self.ssl);
            SslMethod::from_raw(method)
        }
    }
}

macro_rules! make_LibSslError {
@@ -888,8 +914,16 @@ impl<S: Read+Write> IndirectStream<S> {
                LibSslError::ErrorWantRead => {
                    try_ssl_stream!(self.flush());
                    let len = try_ssl_stream!(self.stream.read(&mut self.buf[..]));


                    if len == 0 {
                        let method = self.ssl.get_ssl_method();

                        if method.map(|m| m.is_dtls()).unwrap_or(false) {
                            return Ok(0);
                        } else {
                            self.ssl.get_rbio().set_eof(true);
                        }
                    } else {
                        try_ssl_stream!(self.ssl.get_rbio().write_all(&self.buf[..len]));
                    }
+6 −1
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ macro_rules! run_test(
            use std::net::TcpStream;
            use ssl;
            use ssl::SslMethod;
            use ssl::{SslContext, SslStream, VerifyCallback};
            use ssl::{SslContext, Ssl, SslStream, VerifyCallback};
            use ssl::SSL_VERIFY_PEER;
            use crypto::hash::Type::SHA256;
            use x509::X509StoreContext;
@@ -86,6 +86,11 @@ run_test!(new_sslstream, |method, stream| {
    SslStream::connect_generic(&SslContext::new(method).unwrap(), stream).unwrap();
});

run_test!(get_ssl_method, |method, _| {
    let ssl = Ssl::new(&SslContext::new(method).unwrap()).unwrap();
    assert_eq!(ssl.get_ssl_method(), Some(method));
});

run_test!(verify_untrusted, |method, stream| {
    let mut ctx = SslContext::new(method).unwrap();
    ctx.set_verify(SSL_VERIFY_PEER, None);