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 c8d23f3.

Conflicts:
	openssl/src/ssl/mod.rs
This commit is contained in:
Manuel Schölling 2015-07-18 12:48:40 +02:00
parent 2e0ae7a8ca
commit a43011d77c
3 changed files with 42 additions and 2 deletions

View File

@ -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;

View File

@ -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 {
self.ssl.get_rbio().set_eof(true);
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]));
}

View File

@ -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);