commit
11059e1b2d
22
.travis.yml
22
.travis.yml
|
|
@ -5,13 +5,25 @@ os:
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- secure: J4i75AV4KMrU/UQrLIzzIh35Xix40Ki0uWjm8j05oxlXVl5aPU2zB30AemDne2QXYzkN4kRG/iRnNORE/8D0lF7YipQNSNxgfiBVoOEfj/NSogvI2BftYX9vlLZJUvt+s/nbE3xa/Pyge1IPv7itDYGO7SMe8RTSqitgqyfE2Eg=
|
- secure: J4i75AV4KMrU/UQrLIzzIh35Xix40Ki0uWjm8j05oxlXVl5aPU2zB30AemDne2QXYzkN4kRG/iRnNORE/8D0lF7YipQNSNxgfiBVoOEfj/NSogvI2BftYX9vlLZJUvt+s/nbE3xa/Pyge1IPv7itDYGO7SMe8RTSqitgqyfE2Eg=
|
||||||
- FEATURES="tlsv1_1 tlsv1_2 aes_xts npn"
|
- FEATURES="tlsv1_1 tlsv1_2 dtlsv1 aes_xts npn"
|
||||||
|
before_install:
|
||||||
|
- DIR=`pwd`
|
||||||
|
- (test $TRAVIS_OS_NAME == "osx" || (sudo apt-get install gcc make))
|
||||||
|
- (test $TRAVIS_OS_NAME == "osx" || (wget https://openssl.org/source/openssl-1.0.2-latest.tar.gz -O /tmp/openssl-1.0.2-latest.tar.gz))
|
||||||
|
- (test $TRAVIS_OS_NAME == "osx" || (cd /tmp && tar xzf openssl-1.0.2-latest.tar.gz))
|
||||||
|
- (test $TRAVIS_OS_NAME == "osx" || (cd /tmp/openssl-1.0.2*/ && ./config --prefix=/usr/ shared))
|
||||||
|
- (test $TRAVIS_OS_NAME == "osx" || (cd /tmp/openssl-1.0.2*/ && make))
|
||||||
|
- (test $TRAVIS_OS_NAME == "osx" || (cd /tmp/openssl-1.0.2*/ && sudo make install))
|
||||||
|
- cd ${DIR}
|
||||||
before_script:
|
before_script:
|
||||||
- openssl s_server -accept 15418 -www -cert openssl/test/cert.pem -key openssl/test/key.pem >/dev/null 2>&1 &
|
- openssl version
|
||||||
- openssl s_server -accept 15419 -www -cert openssl/test/cert.pem -key openssl/test/key.pem -nextprotoneg "http/1.1,spdy/3.1" >/dev/null 2>&1 &
|
- openssl s_server -accept 15418 -www -cert openssl/test/cert.pem -key openssl/test/key.pem >/dev/null 2>&1 &
|
||||||
|
- openssl s_server -accept 15419 -www -cert openssl/test/cert.pem -key openssl/test/key.pem -nextprotoneg "http/1.1,spdy/3.1" >/dev/null 2>&1 &
|
||||||
script:
|
script:
|
||||||
- (cd openssl && cargo test)
|
- (cd openssl && LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test)
|
||||||
- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && cargo test --features "$FEATURES"))
|
- (test $TRAVIS_OS_NAME == "osx" || (./openssl/test/test.sh &))
|
||||||
|
- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test --features "$FEATURES"))
|
||||||
|
- (test $TRAVIS_OS_NAME == "osx" || killall openssl)
|
||||||
- ./.travis/build_docs.sh
|
- ./.travis/build_docs.sh
|
||||||
after_success:
|
after_success:
|
||||||
- test $TRAVIS_PULL_REQUEST == "false" && test $TRAVIS_BRANCH == "master" && ./.travis/update_docs.sh
|
- test $TRAVIS_PULL_REQUEST == "false" && test $TRAVIS_BRANCH == "master" && ./.travis/update_docs.sh
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ rust-openssl directory. Then run one of the following commands:
|
||||||
|
|
||||||
* Windows: `openssl s_server -accept 15418 -www -cert test/cert.pem -key
|
* Windows: `openssl s_server -accept 15418 -www -cert test/cert.pem -key
|
||||||
test/key.pem > NUL`
|
test/key.pem > NUL`
|
||||||
* Linux: `openssl s_server -accept 15418 -www -cert test/cert.pem -key
|
* Linux: `openssl s_server -accept 15418 -www -cert test/cert.pem -key \
|
||||||
test/key.pem >/dev/null`
|
test/key.pem >/dev/null`
|
||||||
|
|
||||||
Then in the original terminal, run `cargo test`. If everything is set up
|
Then in the original terminal, run `cargo test`. If everything is set up
|
||||||
|
|
@ -71,4 +71,7 @@ correctly, all tests should pass. You might get some warnings in the `openssl
|
||||||
s_server` window. Those aren't anything to worry about. You can stop the server
|
s_server` window. Those aren't anything to worry about. You can stop the server
|
||||||
using Control-C.
|
using Control-C.
|
||||||
|
|
||||||
|
For DTLS testing each test requires its own instance of OpenSSL's s_server. On
|
||||||
|
Linux you can run the bash script in `openssl/tests/test.sh`.
|
||||||
|
|
||||||
[1]: http://slproweb.com/products/Win32OpenSSL.html
|
[1]: http://slproweb.com/products/Win32OpenSSL.html
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ build = "build.rs"
|
||||||
[features]
|
[features]
|
||||||
tlsv1_2 = []
|
tlsv1_2 = []
|
||||||
tlsv1_1 = []
|
tlsv1_1 = []
|
||||||
|
dtlsv1 = []
|
||||||
|
dtlsv1_2 = []
|
||||||
sslv2 = []
|
sslv2 = []
|
||||||
aes_xts = []
|
aes_xts = []
|
||||||
npn = []
|
npn = []
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,7 @@ pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77;
|
||||||
pub const SSL_CTRL_SET_TLSEXT_HOSTNAME: c_int = 55;
|
pub const SSL_CTRL_SET_TLSEXT_HOSTNAME: c_int = 55;
|
||||||
pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14;
|
pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14;
|
||||||
|
|
||||||
|
pub const SSL_CTRL_SET_READ_AHEAD: c_int = 41;
|
||||||
pub const SSL_ERROR_NONE: c_int = 0;
|
pub const SSL_ERROR_NONE: c_int = 0;
|
||||||
pub const SSL_ERROR_SSL: c_int = 1;
|
pub const SSL_ERROR_SSL: c_int = 1;
|
||||||
pub const SSL_ERROR_SYSCALL: c_int = 5;
|
pub const SSL_ERROR_SYSCALL: c_int = 5;
|
||||||
|
|
@ -282,6 +283,9 @@ pub unsafe fn SSL_CTX_add_extra_chain_cert(ssl: *mut SSL_CTX, cert: *mut X509) -
|
||||||
SSL_CTX_ctrl(ssl, SSL_CTRL_EXTRA_CHAIN_CERT, 0, cert)
|
SSL_CTX_ctrl(ssl, SSL_CTRL_EXTRA_CHAIN_CERT, 0, cert)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn SSL_CTX_set_read_ahead(ctx: *mut SSL_CTX, m: c_long) -> c_long {
|
||||||
|
SSL_CTX_ctrl(ctx, SSL_CTRL_SET_READ_AHEAD, m, ptr::null_mut())
|
||||||
|
}
|
||||||
|
|
||||||
// True functions
|
// True functions
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -482,6 +486,10 @@ extern "C" {
|
||||||
pub fn TLSv1_1_method() -> *const SSL_METHOD;
|
pub fn TLSv1_1_method() -> *const SSL_METHOD;
|
||||||
#[cfg(feature = "tlsv1_2")]
|
#[cfg(feature = "tlsv1_2")]
|
||||||
pub fn TLSv1_2_method() -> *const SSL_METHOD;
|
pub fn TLSv1_2_method() -> *const SSL_METHOD;
|
||||||
|
#[cfg(feature = "dtlsv1")]
|
||||||
|
pub fn DTLSv1_method() -> *const SSL_METHOD;
|
||||||
|
#[cfg(feature = "dtlsv1_2")]
|
||||||
|
pub fn DTLSv1_2_method() -> *const SSL_METHOD;
|
||||||
pub fn SSLv23_method() -> *const SSL_METHOD;
|
pub fn SSLv23_method() -> *const SSL_METHOD;
|
||||||
|
|
||||||
pub fn SSL_new(ctx: *mut SSL_CTX) -> *mut SSL;
|
pub fn SSL_new(ctx: *mut SSL_CTX) -> *mut SSL;
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,13 @@ description = "OpenSSL bindings"
|
||||||
repository = "https://github.com/sfackler/rust-openssl"
|
repository = "https://github.com/sfackler/rust-openssl"
|
||||||
documentation = "https://sfackler.github.io/rust-openssl/doc/openssl"
|
documentation = "https://sfackler.github.io/rust-openssl/doc/openssl"
|
||||||
readme = "../README.md"
|
readme = "../README.md"
|
||||||
keywords = ["crypto", "tls", "ssl"]
|
keywords = ["crypto", "tls", "ssl", "dtls"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
tlsv1_2 = ["openssl-sys/tlsv1_2"]
|
tlsv1_2 = ["openssl-sys/tlsv1_2"]
|
||||||
tlsv1_1 = ["openssl-sys/tlsv1_1"]
|
tlsv1_1 = ["openssl-sys/tlsv1_1"]
|
||||||
|
dtlsv1 = ["openssl-sys/dtlsv1"]
|
||||||
|
dtlsv1_2 = ["openssl-sys/dtlsv1_2"]
|
||||||
sslv2 = ["openssl-sys/sslv2"]
|
sslv2 = ["openssl-sys/sslv2"]
|
||||||
aes_xts = ["openssl-sys/aes_xts"]
|
aes_xts = ["openssl-sys/aes_xts"]
|
||||||
npn = ["openssl-sys/npn"]
|
npn = ["openssl-sys/npn"]
|
||||||
|
|
@ -27,3 +29,6 @@ libc = "0.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rustc-serialize = "0.3"
|
rustc-serialize = "0.3"
|
||||||
|
|
||||||
|
[dev-dependencies.connected_socket]
|
||||||
|
connected_socket = "0.0.1"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,10 @@ extern crate openssl_sys as ffi;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate rustc_serialize as serialize;
|
extern crate rustc_serialize as serialize;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(any(feature="dtlsv1", feature="dtlsv1_2"))]
|
||||||
|
extern crate connected_socket;
|
||||||
|
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
pub mod asn1;
|
pub mod asn1;
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,12 @@ pub enum SslMethod {
|
||||||
#[cfg(feature = "tlsv1_2")]
|
#[cfg(feature = "tlsv1_2")]
|
||||||
/// Support TLSv1.2 protocol, requires the `tlsv1_2` feature.
|
/// Support TLSv1.2 protocol, requires the `tlsv1_2` feature.
|
||||||
Tlsv1_2,
|
Tlsv1_2,
|
||||||
|
#[cfg(feature = "dtlsv1")]
|
||||||
|
/// Support DTLSv1 protocol, requires the `dtlsv1` feature.
|
||||||
|
Dtlsv1,
|
||||||
|
#[cfg(feature = "dtlsv1_2")]
|
||||||
|
/// Support DTLSv1.2 protocol, requires the `dtlsv1_2` feature.
|
||||||
|
Dtlsv1_2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SslMethod {
|
impl SslMethod {
|
||||||
|
|
@ -110,9 +116,37 @@ impl SslMethod {
|
||||||
#[cfg(feature = "tlsv1_1")]
|
#[cfg(feature = "tlsv1_1")]
|
||||||
SslMethod::Tlsv1_1 => ffi::TLSv1_1_method(),
|
SslMethod::Tlsv1_1 => ffi::TLSv1_1_method(),
|
||||||
#[cfg(feature = "tlsv1_2")]
|
#[cfg(feature = "tlsv1_2")]
|
||||||
SslMethod::Tlsv1_2 => ffi::TLSv1_2_method()
|
SslMethod::Tlsv1_2 => ffi::TLSv1_2_method(),
|
||||||
|
#[cfg(feature = "dtlsv1")]
|
||||||
|
SslMethod::Dtlsv1 => ffi::DTLSv1_method(),
|
||||||
|
#[cfg(feature = "dtlsv1_2")]
|
||||||
|
SslMethod::Dtlsv1_2 => ffi::DTLSv1_2_method(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "dtlsv1")]
|
||||||
|
pub fn is_dtlsv1(&self) -> bool {
|
||||||
|
*self == SslMethod::Dtlsv1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "dtlsv1_2")]
|
||||||
|
pub fn is_dtlsv1_2(&self) -> bool {
|
||||||
|
*self == SslMethod::Dtlsv1_2
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_dtls(&self) -> bool {
|
||||||
|
self.is_dtlsv1() || self.is_dtlsv1_2()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "dtlsv1"))]
|
||||||
|
pub fn is_dtlsv1(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "dtlsv1_2"))]
|
||||||
|
pub fn is_dtlsv1_2(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines the type of certificate verification used
|
/// Determines the type of certificate verification used
|
||||||
|
|
@ -339,7 +373,13 @@ impl SslContext {
|
||||||
return Err(SslError::get());
|
return Err(SslError::get());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(SslContext { ctx: ctx })
|
let ctx = SslContext { ctx: ctx };
|
||||||
|
|
||||||
|
if method.is_dtls() {
|
||||||
|
ctx.set_read_ahead(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures the certificate verification method for new connections.
|
/// Configures the certificate verification method for new connections.
|
||||||
|
|
@ -350,6 +390,7 @@ impl SslContext {
|
||||||
mem::transmute(verify));
|
mem::transmute(verify));
|
||||||
let f: extern fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int =
|
let f: extern fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int =
|
||||||
raw_verify;
|
raw_verify;
|
||||||
|
|
||||||
ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f));
|
ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -370,6 +411,7 @@ impl SslContext {
|
||||||
mem::transmute(data));
|
mem::transmute(data));
|
||||||
let f: extern fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int =
|
let f: extern fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int =
|
||||||
raw_verify_with_data::<T>;
|
raw_verify_with_data::<T>;
|
||||||
|
|
||||||
ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f));
|
ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -381,6 +423,12 @@ impl SslContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_read_ahead(&self, m: u32) {
|
||||||
|
unsafe {
|
||||||
|
ffi::SSL_CTX_set_read_ahead(self.ctx, m as c_long);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
/// Specifies the file that contains trusted CA certificates.
|
/// Specifies the file that contains trusted CA certificates.
|
||||||
pub fn set_CA_file(&mut self, file: &Path) -> Result<(),SslError> {
|
pub fn set_CA_file(&mut self, file: &Path) -> Result<(),SslError> {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use serialize::hex::FromHex;
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
@ -11,6 +12,7 @@ use std::fs::File;
|
||||||
|
|
||||||
use crypto::hash::Type::{SHA256};
|
use crypto::hash::Type::{SHA256};
|
||||||
use ssl;
|
use ssl;
|
||||||
|
use ssl::SslMethod;
|
||||||
use ssl::SslMethod::Sslv23;
|
use ssl::SslMethod::Sslv23;
|
||||||
use ssl::{SslContext, SslStream, VerifyCallback};
|
use ssl::{SslContext, SslStream, VerifyCallback};
|
||||||
use ssl::SSL_VERIFY_PEER;
|
use ssl::SSL_VERIFY_PEER;
|
||||||
|
|
@ -20,33 +22,86 @@ use x509::X509FileType;
|
||||||
use x509::X509;
|
use x509::X509;
|
||||||
use crypto::pkey::PKey;
|
use crypto::pkey::PKey;
|
||||||
|
|
||||||
#[test]
|
#[cfg(feature="dtlsv1")]
|
||||||
fn test_new_ctx() {
|
use std::net::UdpSocket;
|
||||||
SslContext::new(Sslv23).unwrap();
|
#[cfg(feature="dtlsv1")]
|
||||||
|
use ssl::SslMethod::Dtlsv1;
|
||||||
|
#[cfg(feature="dtlsv1")]
|
||||||
|
use connected_socket::Connect;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod udp {
|
||||||
|
static mut udp_port:u16 = 15410;
|
||||||
|
|
||||||
|
pub fn next_server<'a>() -> String {
|
||||||
|
unsafe {
|
||||||
|
udp_port += 1;
|
||||||
|
format!("127.0.0.1:{}", udp_port)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
macro_rules! run_test(
|
||||||
fn test_new_sslstream() {
|
($module:ident, $blk:expr) => (
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
#[cfg(test)]
|
||||||
SslStream::new(&SslContext::new(Sslv23).unwrap(), stream).unwrap();
|
mod $module {
|
||||||
}
|
use super::udp;
|
||||||
|
use std::io;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::net::UdpSocket;
|
||||||
|
use std::net::TcpStream;
|
||||||
|
use ssl;
|
||||||
|
use ssl::SslMethod;
|
||||||
|
use ssl::{SslContext, SslStream, VerifyCallback};
|
||||||
|
#[cfg(feature="dtlsv1")]
|
||||||
|
use connected_socket::Connect;
|
||||||
|
use ssl::SSL_VERIFY_PEER;
|
||||||
|
use crypto::hash::Type::SHA256;
|
||||||
|
use x509::X509StoreContext;
|
||||||
|
use serialize::hex::FromHex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_verify_untrusted() {
|
fn sslv23() {
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
$blk(SslMethod::Sslv23, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature="dtlsv1")]
|
||||||
|
fn dtlsv1() {
|
||||||
|
let sock = UdpSocket::bind("127.0.0.1:0").unwrap();
|
||||||
|
let server = udp::next_server();
|
||||||
|
let stream = sock.connect(&server[..]).unwrap();
|
||||||
|
|
||||||
|
$blk(SslMethod::Dtlsv1, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
);
|
||||||
|
|
||||||
|
run_test!(new_ctx, |method, _| {
|
||||||
|
SslContext::new(method).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
run_test!(new_sslstream, |method, stream| {
|
||||||
|
SslStream::new(&SslContext::new(method).unwrap(), stream).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
run_test!(verify_untrusted, |method, stream| {
|
||||||
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, None);
|
ctx.set_verify(SSL_VERIFY_PEER, None);
|
||||||
|
|
||||||
match SslStream::new(&ctx, stream) {
|
match SslStream::new(&ctx, stream) {
|
||||||
Ok(_) => panic!("expected failure"),
|
Ok(_) => panic!("expected failure"),
|
||||||
Err(err) => println!("error {:?}", err)
|
Err(err) => println!("error {:?}", err)
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
#[test]
|
run_test!(verify_trusted, |method, stream| {
|
||||||
fn test_verify_trusted() {
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, None);
|
ctx.set_verify(SSL_VERIFY_PEER, None);
|
||||||
|
|
||||||
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(err) => panic!("Unexpected error {:?}", err)
|
Err(err) => panic!("Unexpected error {:?}", err)
|
||||||
|
|
@ -55,41 +110,41 @@ fn test_verify_trusted() {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(err) => panic!("Expected success, got {:?}", err)
|
Err(err) => panic!("Expected success, got {:?}", err)
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
#[test]
|
run_test!(verify_untrusted_callback_override_ok, |method, stream| {
|
||||||
fn test_verify_untrusted_callback_override_ok() {
|
|
||||||
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
|
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
||||||
|
|
||||||
match SslStream::new(&ctx, stream) {
|
match SslStream::new(&ctx, stream) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(err) => panic!("Expected success, got {:?}", err)
|
Err(err) => panic!("Expected success, got {:?}", err)
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
#[test]
|
run_test!(verify_untrusted_callback_override_bad, |method, stream| {
|
||||||
fn test_verify_untrusted_callback_override_bad() {
|
|
||||||
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
|
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
||||||
|
|
||||||
assert!(SslStream::new(&ctx, stream).is_err());
|
assert!(SslStream::new(&ctx, stream).is_err());
|
||||||
}
|
});
|
||||||
|
|
||||||
#[test]
|
run_test!(verify_trusted_callback_override_ok, |method, stream| {
|
||||||
fn test_verify_trusted_callback_override_ok() {
|
|
||||||
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
|
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
||||||
|
|
||||||
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(err) => panic!("Unexpected error {:?}", err)
|
Err(err) => panic!("Unexpected error {:?}", err)
|
||||||
|
|
@ -98,65 +153,64 @@ fn test_verify_trusted_callback_override_ok() {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(err) => panic!("Expected success, got {:?}", err)
|
Err(err) => panic!("Expected success, got {:?}", err)
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
#[test]
|
run_test!(verify_trusted_callback_override_bad, |method, stream| {
|
||||||
fn test_verify_trusted_callback_override_bad() {
|
|
||||||
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
|
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
||||||
|
|
||||||
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(err) => panic!("Unexpected error {:?}", err)
|
Err(err) => panic!("Unexpected error {:?}", err)
|
||||||
}
|
}
|
||||||
assert!(SslStream::new(&ctx, stream).is_err());
|
assert!(SslStream::new(&ctx, stream).is_err());
|
||||||
}
|
});
|
||||||
|
|
||||||
#[test]
|
run_test!(verify_callback_load_certs, |method, stream| {
|
||||||
fn test_verify_callback_load_certs() {
|
|
||||||
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool {
|
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool {
|
||||||
assert!(x509_ctx.get_current_cert().is_some());
|
assert!(x509_ctx.get_current_cert().is_some());
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
|
||||||
assert!(SslStream::new(&ctx, stream).is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
fn test_verify_trusted_get_error_ok() {
|
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
||||||
|
|
||||||
|
assert!(SslStream::new(&ctx, stream).is_ok());
|
||||||
|
});
|
||||||
|
|
||||||
|
run_test!(verify_trusted_get_error_ok, |method, stream| {
|
||||||
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool {
|
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool {
|
||||||
assert!(x509_ctx.get_error().is_none());
|
assert!(x509_ctx.get_error().is_none());
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
||||||
|
|
||||||
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(err) => panic!("Unexpected error {:?}", err)
|
Err(err) => panic!("Unexpected error {:?}", err)
|
||||||
}
|
}
|
||||||
assert!(SslStream::new(&ctx, stream).is_ok());
|
assert!(SslStream::new(&ctx, stream).is_ok());
|
||||||
}
|
});
|
||||||
|
|
||||||
#[test]
|
run_test!(verify_trusted_get_error_err, |method, stream| {
|
||||||
fn test_verify_trusted_get_error_err() {
|
|
||||||
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool {
|
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool {
|
||||||
assert!(x509_ctx.get_error().is_some());
|
assert!(x509_ctx.get_error().is_some());
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
|
||||||
assert!(SslStream::new(&ctx, stream).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
fn test_verify_callback_data() {
|
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
|
||||||
|
|
||||||
|
assert!(SslStream::new(&ctx, stream).is_err());
|
||||||
|
});
|
||||||
|
|
||||||
|
run_test!(verify_callback_data, |method, stream| {
|
||||||
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext, node_id: &Vec<u8>) -> bool {
|
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext, node_id: &Vec<u8>) -> bool {
|
||||||
let cert = x509_ctx.get_current_cert();
|
let cert = x509_ctx.get_current_cert();
|
||||||
match cert {
|
match cert {
|
||||||
|
|
@ -167,8 +221,7 @@ fn test_verify_callback_data() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
|
||||||
|
|
||||||
// Node id was generated as SHA256 hash of certificate "test/cert.pem"
|
// Node id was generated as SHA256 hash of certificate "test/cert.pem"
|
||||||
// in DER format.
|
// in DER format.
|
||||||
|
|
@ -183,7 +236,7 @@ fn test_verify_callback_data() {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(err) => panic!("Expected success, got {:?}", err)
|
Err(err) => panic!("Expected success, got {:?}", err)
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_set_certificate_and_private_key() {
|
fn test_set_certificate_and_private_key() {
|
||||||
|
|
@ -206,30 +259,27 @@ fn test_set_certificate_and_private_key() {
|
||||||
assert!(ctx.check_private_key().is_ok());
|
assert!(ctx.check_private_key().is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
run_test!(get_ctx_options, |method, _| {
|
||||||
fn test_get_ctx_options() {
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
|
||||||
ctx.get_options();
|
ctx.get_options();
|
||||||
}
|
});
|
||||||
|
|
||||||
#[test]
|
run_test!(set_ctx_options, |method, _| {
|
||||||
fn test_set_ctx_options() {
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
|
||||||
let opts = ctx.set_options(ssl::SSL_OP_NO_TICKET);
|
let opts = ctx.set_options(ssl::SSL_OP_NO_TICKET);
|
||||||
assert!(opts.contains(ssl::SSL_OP_NO_TICKET));
|
assert!(opts.contains(ssl::SSL_OP_NO_TICKET));
|
||||||
assert!(!opts.contains(ssl::SSL_OP_CISCO_ANYCONNECT));
|
assert!(!opts.contains(ssl::SSL_OP_CISCO_ANYCONNECT));
|
||||||
let more_opts = ctx.set_options(ssl::SSL_OP_CISCO_ANYCONNECT);
|
let more_opts = ctx.set_options(ssl::SSL_OP_CISCO_ANYCONNECT);
|
||||||
assert!(more_opts.contains(ssl::SSL_OP_NO_TICKET));
|
assert!(more_opts.contains(ssl::SSL_OP_NO_TICKET));
|
||||||
assert!(more_opts.contains(ssl::SSL_OP_CISCO_ANYCONNECT));
|
assert!(more_opts.contains(ssl::SSL_OP_CISCO_ANYCONNECT));
|
||||||
}
|
});
|
||||||
|
|
||||||
#[test]
|
run_test!(clear_ctx_options, |method, _| {
|
||||||
fn test_clear_ctx_options() {
|
let mut ctx = SslContext::new(method).unwrap();
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
|
||||||
ctx.set_options(ssl::SSL_OP_ALL);
|
ctx.set_options(ssl::SSL_OP_ALL);
|
||||||
let opts = ctx.clear_options(ssl::SSL_OP_ALL);
|
let opts = ctx.clear_options(ssl::SSL_OP_ALL);
|
||||||
assert!(!opts.contains(ssl::SSL_OP_ALL));
|
assert!(!opts.contains(ssl::SSL_OP_ALL));
|
||||||
}
|
});
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_write() {
|
fn test_write() {
|
||||||
|
|
@ -241,13 +291,25 @@ fn test_write() {
|
||||||
stream.flush().unwrap();
|
stream.flush().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "dtlsv1")]
|
||||||
|
fn test_write_dtlsv1() {
|
||||||
|
let sock = UdpSocket::bind("127.0.0.1:0").unwrap();
|
||||||
|
let stream = sock.connect("127.0.0.1:15410").unwrap();
|
||||||
|
|
||||||
|
let mut stream = SslStream::new(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap();
|
||||||
|
stream.write_all("hello".as_bytes()).unwrap();
|
||||||
|
stream.flush().unwrap();
|
||||||
|
stream.write_all(" there".as_bytes()).unwrap();
|
||||||
|
stream.flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_read() {
|
fn test_read() {
|
||||||
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
|
let tcp = TcpStream::connect("127.0.0.1:15418").unwrap();
|
||||||
let mut stream = SslStream::new(&SslContext::new(Sslv23).unwrap(), stream).unwrap();
|
let mut stream = SslStream::new(&SslContext::new(Sslv23).unwrap(), tcp).unwrap();
|
||||||
stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap();
|
stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap();
|
||||||
stream.flush().unwrap();
|
stream.flush().unwrap();
|
||||||
println!("written");
|
|
||||||
io::copy(&mut stream, &mut io::sink()).ok().expect("read error");
|
io::copy(&mut stream, &mut io::sink()).ok().expect("read error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,7 +323,7 @@ fn test_connect_with_unilateral_npn() {
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, None);
|
ctx.set_verify(SSL_VERIFY_PEER, None);
|
||||||
ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]);
|
ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]);
|
||||||
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
||||||
Ok(_)=> {}
|
Ok(_) => {}
|
||||||
Err(err) => panic!("Unexpected error {:?}", err)
|
Err(err) => panic!("Unexpected error {:?}", err)
|
||||||
}
|
}
|
||||||
let stream = match SslStream::new(&ctx, stream) {
|
let stream = match SslStream::new(&ctx, stream) {
|
||||||
|
|
@ -285,7 +347,7 @@ fn test_connect_with_npn_successful_multiple_matching() {
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, None);
|
ctx.set_verify(SSL_VERIFY_PEER, None);
|
||||||
ctx.set_npn_protocols(&[b"spdy/3.1", b"http/1.1"]);
|
ctx.set_npn_protocols(&[b"spdy/3.1", b"http/1.1"]);
|
||||||
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
||||||
Ok(_)=> {}
|
Ok(_) => {}
|
||||||
Err(err) => panic!("Unexpected error {:?}", err)
|
Err(err) => panic!("Unexpected error {:?}", err)
|
||||||
}
|
}
|
||||||
let stream = match SslStream::new(&ctx, stream) {
|
let stream = match SslStream::new(&ctx, stream) {
|
||||||
|
|
@ -310,7 +372,7 @@ fn test_connect_with_npn_successful_single_match() {
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, None);
|
ctx.set_verify(SSL_VERIFY_PEER, None);
|
||||||
ctx.set_npn_protocols(&[b"spdy/3.1"]);
|
ctx.set_npn_protocols(&[b"spdy/3.1"]);
|
||||||
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
||||||
Ok(_)=> {}
|
Ok(_) => {}
|
||||||
Err(err) => panic!("Unexpected error {:?}", err)
|
Err(err) => panic!("Unexpected error {:?}", err)
|
||||||
}
|
}
|
||||||
let stream = match SslStream::new(&ctx, stream) {
|
let stream = match SslStream::new(&ctx, stream) {
|
||||||
|
|
@ -350,7 +412,7 @@ fn test_npn_server_advertise_multiple() {
|
||||||
ctx.set_verify(SSL_VERIFY_PEER, None);
|
ctx.set_verify(SSL_VERIFY_PEER, None);
|
||||||
ctx.set_npn_protocols(&[b"spdy/3.1"]);
|
ctx.set_npn_protocols(&[b"spdy/3.1"]);
|
||||||
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
|
||||||
Ok(_)=> {}
|
Ok(_) => {}
|
||||||
Err(err) => panic!("Unexpected error {:?}", err)
|
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...
|
||||||
|
|
@ -362,3 +424,38 @@ fn test_npn_server_advertise_multiple() {
|
||||||
// SPDY is selected since that's the only thing the client supports.
|
// SPDY is selected since that's the only thing the client supports.
|
||||||
assert_eq!(b"spdy/3.1", stream.get_selected_npn_protocol().unwrap());
|
assert_eq!(b"spdy/3.1", stream.get_selected_npn_protocol().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature="dtlsv1")]
|
||||||
|
#[cfg(test)]
|
||||||
|
mod dtlsv1 {
|
||||||
|
use serialize::hex::FromHex;
|
||||||
|
use std::net::TcpStream;
|
||||||
|
use std::old_io::{Writer};
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
|
use crypto::hash::Type::{SHA256};
|
||||||
|
use ssl::SslMethod;
|
||||||
|
use ssl::SslMethod::Dtlsv1;
|
||||||
|
use ssl::{SslContext, SslStream, VerifyCallback};
|
||||||
|
use ssl::SSL_VERIFY_PEER;
|
||||||
|
use x509::{X509StoreContext};
|
||||||
|
|
||||||
|
const PROTOCOL:SslMethod = Dtlsv1;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_new_ctx() {
|
||||||
|
SslContext::new(PROTOCOL).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "dtlsv1")]
|
||||||
|
fn test_read_dtlsv1() {
|
||||||
|
let sock = UdpSocket::bind("127.0.0.1:0").unwrap();
|
||||||
|
let server = udp::next_server();
|
||||||
|
let stream = sock.connect(&server[..]).unwrap();
|
||||||
|
|
||||||
|
let mut stream = SslStream::new(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap();
|
||||||
|
let mut buf = [0u8;100];
|
||||||
|
assert!(stream.read(&mut buf).is_ok());
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/bash
|
||||||
|
if test "$TRAVIS_OS_NAME" == "osx"; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
|
||||||
|
|
||||||
|
openssl s_server -accept 15418 -www -cert openssl/test/cert.pem -key openssl/test/key.pem >/dev/null 2>&1 &
|
||||||
|
|
||||||
|
for port in `seq 15411 15430`; do
|
||||||
|
echo hello | openssl s_server -accept $port -dtls1 -cert openssl/test/cert.pem \
|
||||||
|
-key openssl/test/key.pem 2>&1 >/dev/null &
|
||||||
|
done
|
||||||
|
|
||||||
|
# the server for the test ssl::tests::test_write_dtlsv1 must wait to receive
|
||||||
|
# data from the client
|
||||||
|
yes | openssl s_server -accept 15410 -dtls1 -cert openssl/test/cert.pem \
|
||||||
|
-key openssl/test/key.pem 2>&1 >/dev/null
|
||||||
Loading…
Reference in New Issue