Merge pull request #472 from sfackler/alpn-test
Fix test_alpn_server_select_none
This commit is contained in:
commit
1fe16382e0
|
|
@ -318,6 +318,18 @@ pub unsafe fn SSL_set_tlsext_host_name(s: *mut SSL, name: *mut c_char) -> c_long
|
||||||
name as *mut c_void)
|
name as *mut c_void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ERR_GET_LIB(l: c_ulong) -> c_int {
|
||||||
|
((l >> 24) & 0x0FF) as c_int
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ERR_GET_FUNC(l: c_ulong) -> c_int {
|
||||||
|
((l >> 12) & 0xFFF) as c_int
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ERR_GET_REASON(l: c_ulong) -> c_int {
|
||||||
|
(l & 0xFFF) as c_int
|
||||||
|
}
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int;
|
pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int;
|
||||||
pub fn ASN1_STRING_type_new(ty: c_int) -> *mut ASN1_STRING;
|
pub fn ASN1_STRING_type_new(ty: c_int) -> *mut ASN1_STRING;
|
||||||
|
|
|
||||||
|
|
@ -76,39 +76,79 @@ impl Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the raw OpenSSL error code for this error.
|
/// Returns the raw OpenSSL error code for this error.
|
||||||
pub fn error_code(&self) -> c_ulong {
|
pub fn code(&self) -> c_ulong {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the name of the library reporting the error.
|
/// Returns the name of the library reporting the error, if available.
|
||||||
pub fn library(&self) -> &'static str {
|
pub fn library(&self) -> Option<&'static str> {
|
||||||
get_lib(self.0)
|
unsafe {
|
||||||
|
let cstr = ffi::ERR_lib_error_string(self.0);
|
||||||
|
if cstr.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
||||||
|
Some(str::from_utf8(bytes).unwrap())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the name of the function reporting the error.
|
/// Returns the name of the function reporting the error.
|
||||||
pub fn function(&self) -> &'static str {
|
pub fn function(&self) -> Option<&'static str> {
|
||||||
get_func(self.0)
|
unsafe {
|
||||||
|
let cstr = ffi::ERR_func_error_string(self.0);
|
||||||
|
if cstr.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
||||||
|
Some(str::from_utf8(bytes).unwrap())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the reason for the error.
|
/// Returns the reason for the error.
|
||||||
pub fn reason(&self) -> &'static str {
|
pub fn reason(&self) -> Option<&'static str> {
|
||||||
get_reason(self.0)
|
unsafe {
|
||||||
|
let cstr = ffi::ERR_reason_error_string(self.0);
|
||||||
|
if cstr.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
||||||
|
Some(str::from_utf8(bytes).unwrap())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Error {
|
impl fmt::Debug for Error {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt.debug_struct("Error")
|
let mut builder = fmt.debug_struct("Error");
|
||||||
.field("library", &self.library())
|
builder.field("code", &self.code());
|
||||||
.field("function", &self.function())
|
if let Some(library) = self.library() {
|
||||||
.field("reason", &self.reason())
|
builder.field("library", &library);
|
||||||
.finish()
|
}
|
||||||
|
if let Some(function) = self.function() {
|
||||||
|
builder.field("function", &function);
|
||||||
|
}
|
||||||
|
if let Some(reason) = self.reason() {
|
||||||
|
builder.field("reason", &reason);
|
||||||
|
}
|
||||||
|
builder.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt.write_str(&self.reason())
|
try!(write!(fmt, "error:{:08X}", self.0));
|
||||||
|
match self.library() {
|
||||||
|
Some(l) => try!(write!(fmt, ":{}", l)),
|
||||||
|
None => try!(write!(fmt, ":lib({})", ffi::ERR_GET_LIB(self.0))),
|
||||||
|
}
|
||||||
|
match self.function() {
|
||||||
|
Some(f) => try!(write!(fmt, ":{}", f)),
|
||||||
|
None => try!(write!(fmt, ":func({})", ffi::ERR_GET_FUNC(self.0))),
|
||||||
|
}
|
||||||
|
match self.reason() {
|
||||||
|
Some(r) => write!(fmt, ":{}", r),
|
||||||
|
None => write!(fmt, ":reason({})", ffi::ERR_GET_FUNC(self.0)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,31 +157,3 @@ impl error::Error for Error {
|
||||||
"An OpenSSL error"
|
"An OpenSSL error"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_lib(err: c_ulong) -> &'static str {
|
|
||||||
unsafe {
|
|
||||||
let cstr = ffi::ERR_lib_error_string(err);
|
|
||||||
assert!(!cstr.is_null(), "bad lib: {}", err);
|
|
||||||
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
|
||||||
str::from_utf8(bytes).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_func(err: c_ulong) -> &'static str {
|
|
||||||
unsafe {
|
|
||||||
let cstr = ffi::ERR_func_error_string(err);
|
|
||||||
assert!(!cstr.is_null(), "bad func: {}", err);
|
|
||||||
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
|
||||||
str::from_utf8(bytes).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_reason(err: c_ulong) -> &'static str {
|
|
||||||
unsafe {
|
|
||||||
let cstr = ffi::ERR_reason_error_string(err);
|
|
||||||
assert!(!cstr.is_null(), "bad reason: {}", err);
|
|
||||||
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
|
||||||
str::from_utf8(bytes).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -726,10 +726,7 @@ fn test_alpn_server_advertise_multiple() {
|
||||||
/// Test that Servers supporting ALPN don't report a protocol when none of their protocols match
|
/// Test that Servers supporting ALPN don't report a protocol when none of their protocols match
|
||||||
/// the client's reported protocol.
|
/// the client's reported protocol.
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "openssl-102")]
|
#[cfg(all(feature = "openssl-102", ossl102))]
|
||||||
// TODO: not sure why this test is failing on OpenSSL 1.1.0, may be related to
|
|
||||||
// something about SSLv3 though?
|
|
||||||
#[cfg_attr(ossl110, ignore)]
|
|
||||||
fn test_alpn_server_select_none() {
|
fn test_alpn_server_select_none() {
|
||||||
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||||
let localhost = listener.local_addr().unwrap();
|
let localhost = listener.local_addr().unwrap();
|
||||||
|
|
@ -753,21 +750,46 @@ fn test_alpn_server_select_none() {
|
||||||
let mut ctx = SslContext::new(Tls).unwrap();
|
let mut ctx = SslContext::new(Tls).unwrap();
|
||||||
ctx.set_verify(SSL_VERIFY_PEER);
|
ctx.set_verify(SSL_VERIFY_PEER);
|
||||||
ctx.set_alpn_protocols(&[b"http/2"]);
|
ctx.set_alpn_protocols(&[b"http/2"]);
|
||||||
match ctx.set_CA_file(&Path::new("test/root-ca.pem")) {
|
ctx.set_CA_file(&Path::new("test/root-ca.pem")).unwrap();
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => panic!("Unexpected error {:?}", err),
|
|
||||||
}
|
|
||||||
// Now connect to the socket and make sure the protocol negotiation works...
|
// Now connect to the socket and make sure the protocol negotiation works...
|
||||||
let stream = TcpStream::connect(localhost).unwrap();
|
let stream = TcpStream::connect(localhost).unwrap();
|
||||||
let stream = match SslStream::connect(&ctx, stream) {
|
let stream = SslStream::connect(&ctx, stream).unwrap();
|
||||||
Ok(stream) => stream,
|
|
||||||
Err(err) => panic!("Expected success, got {:?}", err),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Since the protocols from the server and client don't overlap at all, no protocol is selected
|
// Since the protocols from the server and client don't overlap at all, no protocol is selected
|
||||||
assert_eq!(None, stream.ssl().selected_alpn_protocol());
|
assert_eq!(None, stream.ssl().selected_alpn_protocol());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In 1.1.0, ALPN negotiation failure is a fatal error
|
||||||
|
#[test]
|
||||||
|
#[cfg(all(feature = "openssl-102", ossl110))]
|
||||||
|
fn test_alpn_server_select_none() {
|
||||||
|
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||||
|
let localhost = listener.local_addr().unwrap();
|
||||||
|
// We create a different context instance for the server...
|
||||||
|
let listener_ctx = {
|
||||||
|
let mut ctx = SslContext::new(Tls).unwrap();
|
||||||
|
ctx.set_verify(SSL_VERIFY_PEER);
|
||||||
|
ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]);
|
||||||
|
assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM)
|
||||||
|
.is_ok());
|
||||||
|
ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM)
|
||||||
|
.unwrap();
|
||||||
|
ctx
|
||||||
|
};
|
||||||
|
// Have the listener wait on the connection in a different thread.
|
||||||
|
thread::spawn(move || {
|
||||||
|
let (stream, _) = listener.accept().unwrap();
|
||||||
|
assert!(SslStream::accept(&listener_ctx, stream).is_err());
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut ctx = SslContext::new(Tls).unwrap();
|
||||||
|
ctx.set_verify(SSL_VERIFY_PEER);
|
||||||
|
ctx.set_alpn_protocols(&[b"http/2"]);
|
||||||
|
ctx.set_CA_file(&Path::new("test/root-ca.pem")).unwrap();
|
||||||
|
// Now connect to the socket and make sure the protocol negotiation works...
|
||||||
|
let stream = TcpStream::connect(localhost).unwrap();
|
||||||
|
assert!(SslStream::connect(&ctx, stream).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod dtlsv1 {
|
mod dtlsv1 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue