aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/ssl
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2015-04-05 16:45:24 -0700
committerSteven Fackler <[email protected]>2015-04-05 16:45:24 -0700
commit36f264551ad410833877f3884ce390456b8127dd (patch)
tree04afb895c278bb9db91523bb2427302ce87079f9 /openssl/src/ssl
parentRelease v0.5.5 (diff)
parentFix errors in tests (SslVerifyPeer -> SSL_VERIFY_PEER) (diff)
downloadrust-openssl-36f264551ad410833877f3884ce390456b8127dd.tar.xz
rust-openssl-36f264551ad410833877f3884ce390456b8127dd.zip
Merge pull request #186 from manuels/set_raw_key
Use raw keys and certs in SslContext
Diffstat (limited to 'openssl/src/ssl')
-rw-r--r--openssl/src/ssl/mod.rs69
-rw-r--r--openssl/src/ssl/tests.rs94
2 files changed, 112 insertions, 51 deletions
diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs
index dc23b79d..4c0b13f1 100644
--- a/openssl/src/ssl/mod.rs
+++ b/openssl/src/ssl/mod.rs
@@ -22,6 +22,7 @@ use bio::{MemBio};
use ffi;
use ssl::error::{SslError, SslSessionClosed, StreamError, OpenSslErrors};
use x509::{X509StoreContext, X509FileType, X509};
+use crypto::pkey::PKey;
pub mod error;
#[cfg(test)]
@@ -115,13 +116,16 @@ impl SslMethod {
}
/// Determines the type of certificate verification used
-#[derive(Copy, Clone, Debug)]
-#[repr(i32)]
-pub enum SslVerifyMode {
- /// Verify that the server's certificate is trusted
- SslVerifyPeer = ffi::SSL_VERIFY_PEER,
- /// Do not verify the server's certificate
- SslVerifyNone = ffi::SSL_VERIFY_NONE
+bitflags! {
+ flags SslVerifyMode: i32 {
+ /// Verify that the server's certificate is trusted
+ const SSL_VERIFY_PEER = ffi::SSL_VERIFY_PEER,
+ /// Do not verify the server's certificate
+ const SSL_VERIFY_NONE = ffi::SSL_VERIFY_NONE,
+ /// Terminate handshake if client did not return a certificate.
+ /// Use together with SSL_VERIFY_PEER.
+ const SSL_VERIFY_FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ }
}
lazy_static! {
@@ -296,11 +300,11 @@ pub type VerifyCallbackData<T> = fn(preverify_ok: bool,
// FIXME: macro may be instead of inlining?
#[inline]
-fn wrap_ssl_result(res: c_int) -> Option<SslError> {
+fn wrap_ssl_result(res: c_int) -> Result<(),SslError> {
if res == 0 {
- Some(SslError::get())
+ Err(SslError::get())
} else {
- None
+ Ok(())
}
}
@@ -346,7 +350,7 @@ impl SslContext {
mem::transmute(verify));
let f: extern fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int =
raw_verify;
- ffi::SSL_CTX_set_verify(self.ctx, mode as c_int, Some(f));
+ ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f));
}
}
@@ -366,7 +370,7 @@ impl SslContext {
mem::transmute(data));
let f: extern fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int =
raw_verify_with_data::<T>;
- ffi::SSL_CTX_set_verify(self.ctx, mode as c_int, Some(f));
+ ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f));
}
}
@@ -379,7 +383,7 @@ impl SslContext {
#[allow(non_snake_case)]
/// Specifies the file that contains trusted CA certificates.
- pub fn set_CA_file(&mut self, file: &Path) -> Option<SslError> {
+ pub fn set_CA_file(&mut self, file: &Path) -> Result<(),SslError> {
let file = CString::new(file.as_os_str().to_str().expect("invalid utf8")).unwrap();
wrap_ssl_result(
unsafe {
@@ -389,7 +393,7 @@ impl SslContext {
/// Specifies the file that contains certificate
pub fn set_certificate_file(&mut self, file: &Path,
- file_type: X509FileType) -> Option<SslError> {
+ file_type: X509FileType) -> Result<(),SslError> {
let file = CString::new(file.as_os_str().to_str().expect("invalid utf8")).unwrap();
wrap_ssl_result(
unsafe {
@@ -397,9 +401,26 @@ impl SslContext {
})
}
+ /// Specifies the certificate
+ pub fn set_certificate(&mut self, cert: &X509) -> Result<(),SslError> {
+ wrap_ssl_result(
+ unsafe {
+ ffi::SSL_CTX_use_certificate(self.ctx, cert.get_handle())
+ })
+ }
+
+ /// Adds a certificate to the certificate chain presented together with the
+ /// certificate specified using set_certificate()
+ pub fn add_extra_chain_cert(&mut self, cert: &X509) -> Result<(),SslError> {
+ wrap_ssl_result(
+ unsafe {
+ ffi::SSL_CTX_add_extra_chain_cert(self.ctx, cert.get_handle()) as c_int
+ })
+ }
+
/// Specifies the file that contains private key
pub fn set_private_key_file(&mut self, file: &Path,
- file_type: X509FileType) -> Option<SslError> {
+ file_type: X509FileType) -> Result<(),SslError> {
let file = CString::new(file.as_os_str().to_str().expect("invalid utf8")).unwrap();
wrap_ssl_result(
unsafe {
@@ -407,7 +428,23 @@ impl SslContext {
})
}
- pub fn set_cipher_list(&mut self, cipher_list: &str) -> Option<SslError> {
+ /// Specifies the private key
+ pub fn set_private_key(&mut self, key: &PKey) -> Result<(),SslError> {
+ wrap_ssl_result(
+ unsafe {
+ ffi::SSL_CTX_use_PrivateKey(self.ctx, key.get_handle())
+ })
+ }
+
+ /// Check consistency of private key and certificate
+ pub fn check_private_key(&mut self) -> Result<(),SslError> {
+ wrap_ssl_result(
+ unsafe {
+ ffi::SSL_CTX_check_private_key(self.ctx)
+ })
+ }
+
+ pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(),SslError> {
wrap_ssl_result(
unsafe {
let cipher_list = CString::new(cipher_list.as_bytes()).unwrap();
diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs
index 5322ebde..05c9fe79 100644
--- a/openssl/src/ssl/tests.rs
+++ b/openssl/src/ssl/tests.rs
@@ -7,15 +7,18 @@ use std::path::Path;
use std::net::TcpListener;
#[cfg(feature = "npn")]
use std::thread;
+use std::fs::File;
use crypto::hash::Type::{SHA256};
use ssl;
use ssl::SslMethod::Sslv23;
use ssl::{SslContext, SslStream, VerifyCallback};
-use ssl::SslVerifyMode::SslVerifyPeer;
+use ssl::SSL_VERIFY_PEER;
use x509::X509StoreContext;
#[cfg(feature = "npn")]
use x509::X509FileType;
+use x509::X509;
+use crypto::pkey::PKey;
#[test]
fn test_new_ctx() {
@@ -32,7 +35,7 @@ fn test_new_sslstream() {
fn test_verify_untrusted() {
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, None);
+ ctx.set_verify(SSL_VERIFY_PEER, None);
match SslStream::new(&ctx, stream) {
Ok(_) => panic!("expected failure"),
Err(err) => println!("error {:?}", err)
@@ -43,10 +46,10 @@ fn test_verify_untrusted() {
fn test_verify_trusted() {
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, None);
+ ctx.set_verify(SSL_VERIFY_PEER, None);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
- None => {}
- Some(err) => panic!("Unexpected error {:?}", err)
+ Ok(_) => {}
+ Err(err) => panic!("Unexpected error {:?}", err)
}
match SslStream::new(&ctx, stream) {
Ok(_) => (),
@@ -61,7 +64,7 @@ fn test_verify_untrusted_callback_override_ok() {
}
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback));
+ ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
match SslStream::new(&ctx, stream) {
Ok(_) => (),
Err(err) => panic!("Expected success, got {:?}", err)
@@ -75,7 +78,7 @@ fn test_verify_untrusted_callback_override_bad() {
}
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback));
+ ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
assert!(SslStream::new(&ctx, stream).is_err());
}
@@ -86,10 +89,10 @@ fn test_verify_trusted_callback_override_ok() {
}
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback));
+ ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
- None => {}
- Some(err) => panic!("Unexpected error {:?}", err)
+ Ok(_) => {}
+ Err(err) => panic!("Unexpected error {:?}", err)
}
match SslStream::new(&ctx, stream) {
Ok(_) => (),
@@ -104,10 +107,10 @@ fn test_verify_trusted_callback_override_bad() {
}
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback));
+ ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
- None => {}
- Some(err) => panic!("Unexpected error {:?}", err)
+ Ok(_) => {}
+ Err(err) => panic!("Unexpected error {:?}", err)
}
assert!(SslStream::new(&ctx, stream).is_err());
}
@@ -120,7 +123,7 @@ fn test_verify_callback_load_certs() {
}
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback));
+ ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
assert!(SslStream::new(&ctx, stream).is_ok());
}
@@ -132,10 +135,10 @@ fn test_verify_trusted_get_error_ok() {
}
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback));
+ ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
- None => {}
- Some(err) => panic!("Unexpected error {:?}", err)
+ Ok(_) => {}
+ Err(err) => panic!("Unexpected error {:?}", err)
}
assert!(SslStream::new(&ctx, stream).is_ok());
}
@@ -148,7 +151,7 @@ fn test_verify_trusted_get_error_err() {
}
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback));
+ ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
assert!(SslStream::new(&ctx, stream).is_err());
}
@@ -173,7 +176,7 @@ fn test_verify_callback_data() {
// Please update if "test/cert.pem" will ever change
let node_hash_str = "46e3f1a6d17a41ce70d0c66ef51cee2ab4ba67cac8940e23f10c1f944b49fb5c";
let node_id = node_hash_str.from_hex().unwrap();
- ctx.set_verify_with_data(SslVerifyPeer, callback, node_id);
+ ctx.set_verify_with_data(SSL_VERIFY_PEER, callback, node_id);
ctx.set_verify_depth(1);
match SslStream::new(&ctx, stream) {
@@ -183,6 +186,27 @@ fn test_verify_callback_data() {
}
#[test]
+fn test_set_certificate_and_private_key() {
+ let key_path = Path::new("test/key.pem");
+ let cert_path = Path::new("test/cert.pem");
+ let mut key_file = File::open(&key_path)
+ .ok()
+ .expect("Failed to open `test/key.pem`");
+ let mut cert_file = File::open(&cert_path)
+ .ok()
+ .expect("Failed to open `test/cert.pem`");
+
+ let key = PKey::private_key_from_pem(&mut key_file).unwrap();
+ let cert = X509::from_pem(&mut cert_file).unwrap();
+
+ let mut ctx = SslContext::new(Sslv23).unwrap();
+ ctx.set_private_key(&key).unwrap();
+ ctx.set_certificate(&cert).unwrap();
+
+ assert!(ctx.check_private_key().is_ok());
+}
+
+#[test]
fn test_get_ctx_options() {
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.get_options();
@@ -234,11 +258,11 @@ fn test_read() {
fn test_connect_with_unilateral_npn() {
let stream = TcpStream::connect("127.0.0.1:15418").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, None);
+ ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
- None => {}
- Some(err) => panic!("Unexpected error {:?}", err)
+ Ok(_)=> {}
+ Err(err) => panic!("Unexpected error {:?}", err)
}
let stream = match SslStream::new(&ctx, stream) {
Ok(stream) => stream,
@@ -258,11 +282,11 @@ fn test_connect_with_npn_successful_multiple_matching() {
// NPN enabled.
let stream = TcpStream::connect("127.0.0.1:15419").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, None);
+ ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_npn_protocols(&[b"spdy/3.1", b"http/1.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
- None => {}
- Some(err) => panic!("Unexpected error {:?}", err)
+ Ok(_)=> {}
+ Err(err) => panic!("Unexpected error {:?}", err)
}
let stream = match SslStream::new(&ctx, stream) {
Ok(stream) => stream,
@@ -283,11 +307,11 @@ fn test_connect_with_npn_successful_single_match() {
// NPN enabled.
let stream = TcpStream::connect("127.0.0.1:15419").unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, None);
+ ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_npn_protocols(&[b"spdy/3.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
- None => {}
- Some(err) => panic!("Unexpected error {:?}", err)
+ Ok(_)=> {}
+ Err(err) => panic!("Unexpected error {:?}", err)
}
let stream = match SslStream::new(&ctx, stream) {
Ok(stream) => stream,
@@ -308,12 +332,12 @@ fn test_npn_server_advertise_multiple() {
// We create a different context instance for the server...
let listener_ctx = {
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, None);
+ ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]);
- ctx.set_certificate_file(
- &Path::new("test/cert.pem"), X509FileType::PEM);
+ 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);
+ &Path::new("test/key.pem"), X509FileType::PEM).unwrap();
ctx
};
// Have the listener wait on the connection in a different thread.
@@ -323,11 +347,11 @@ fn test_npn_server_advertise_multiple() {
});
let mut ctx = SslContext::new(Sslv23).unwrap();
- ctx.set_verify(SslVerifyPeer, None);
+ ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_npn_protocols(&[b"spdy/3.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
- None => {}
- Some(err) => panic!("Unexpected error {:?}", err)
+ Ok(_)=> {}
+ Err(err) => panic!("Unexpected error {:?}", err)
}
// Now connect to the socket and make sure the protocol negotiation works...
let stream = TcpStream::connect(localhost).unwrap();