aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/ssl/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openssl/src/ssl/mod.rs')
-rw-r--r--openssl/src/ssl/mod.rs108
1 files changed, 104 insertions, 4 deletions
diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs
index cc9069dc..cd7c1426 100644
--- a/openssl/src/ssl/mod.rs
+++ b/openssl/src/ssl/mod.rs
@@ -1,3 +1,72 @@
+//! SSL/TLS support.
+//!
+//! The `ClientConnector` and `ServerConnector` should be used in most cases - they handle
+//! configuration of the OpenSSL primitives for you.
+//!
+//! # Examples
+//!
+//! To connect as a client to a remote server:
+//!
+//! ```
+//! use openssl::ssl::ClientConnectorBuilder;
+//! use std::io::{Read, Write};
+//! use std::net::TcpStream;
+//!
+//! let connector = ClientConnectorBuilder::tls().unwrap().build();
+//!
+//! let stream = TcpStream::connect("google.com:443").unwrap();
+//! let mut stream = connector.connect("google.com", stream).unwrap();
+//!
+//! stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
+//! let mut res = vec![];
+//! stream.read_to_end(&mut res).unwrap();
+//! println!("{}", String::from_utf8_lossy(&res));
+//! ```
+//!
+//! To accept connections as a server from remote clients:
+//!
+//! ```no_run
+//! use openssl::pkcs12::Pkcs12;
+//! use openssl::ssl::{ServerConnectorBuilder, SslStream};
+//! use std::fs::File;
+//! use std::io::{Read, Write};
+//! use std::net::{TcpListener, TcpStream};
+//! use std::sync::Arc;
+//! use std::thread;
+//!
+//! // In this example we retrieve our keypair and certificate chain from a PKCS #12 archive,
+//! // but but they can also be retrieved from, for example, individual PEM- or DER-formatted
+//! // files. See the documentation for the `PKey` and `X509` types for more details.
+//! let mut file = File::open("identity.pfx").unwrap();
+//! let mut pkcs12 = vec![];
+//! file.read_to_end(&mut pkcs12).unwrap();
+//! let pkcs12 = Pkcs12::from_der(&pkcs12).unwrap();
+//! let identity = pkcs12.parse("password123").unwrap();
+//!
+//! let connector = ServerConnectorBuilder::tls(&identity.pkey, &identity.cert, &identity.chain)
+//! .unwrap()
+//! .build();
+//! let connector = Arc::new(connector);
+//!
+//! let listener = TcpListener::bind("0.0.0.0:8443").unwrap();
+//!
+//! fn handle_client(stream: SslStream<TcpStream>) {
+//! // ...
+//! }
+//!
+//! for stream in listener.incoming() {
+//! match stream {
+//! Ok(stream) => {
+//! let connector = connector.clone();
+//! thread::spawn(move || {
+//! let stream = connector.connect(stream).unwrap();
+//! handle_client(stream);
+//! });
+//! }
+//! Err(e) => { /* connection failed */ }
+//! }
+//! }
+//! ```
use libc::{c_int, c_void, c_long, c_ulong};
use std::any::Any;
use std::any::TypeId;
@@ -22,19 +91,22 @@ use ffi;
use {init, cvt, cvt_p};
use dh::Dh;
use x509::{X509StoreContextRef, X509FileType, X509, X509Ref, X509VerifyError};
-#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
-use x509::verify::X509VerifyParamRef;
-use pkey::PKey;
+#[cfg(any(ossl102, ossl110))]
+use verify::X509VerifyParamRef;
+use pkey::PKeyRef;
use error::ErrorStack;
use opaque::Opaque;
pub mod error;
+mod connector;
mod bio;
#[cfg(test)]
mod tests;
use self::bio::BioMethod;
+pub use ssl::connector::{ClientConnectorBuilder, ClientConnector, ServerConnectorBuilder,
+ ServerConnector};
#[doc(inline)]
pub use ssl::error::Error;
@@ -339,6 +411,7 @@ pub enum SniError {
NoAck,
}
+/// A builder for `SslContext`s.
pub struct SslContextBuilder(*mut ffi::SSL_CTX);
impl Drop for SslContextBuilder {
@@ -529,7 +602,7 @@ impl SslContextBuilder {
}
/// Specifies the private key
- pub fn set_private_key(&mut self, key: &PKey) -> Result<(), ErrorStack> {
+ pub fn set_private_key(&mut self, key: &PKeyRef) -> Result<(), ErrorStack> {
unsafe {
cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ())
}
@@ -790,6 +863,7 @@ impl SslCipherRef {
}
}
+/// A reference to an `Ssl`.
pub struct SslRef(Opaque);
unsafe impl Send for SslRef {}
@@ -1030,6 +1104,11 @@ impl SslRef {
/// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or 1.1.0.
#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
+ self._param_mut()
+ }
+
+ #[cfg(any(ossl102, ossl110))]
+ fn _param_mut(&mut self) -> &mut X509VerifyParamRef {
unsafe {
X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr()))
}
@@ -1096,6 +1175,11 @@ impl Ssl {
}
/// Creates an SSL/TLS client operating over the provided stream.
+ ///
+ /// # Warning
+ ///
+ /// OpenSSL's default configuration is insecure. It is highly recommended to use
+ /// `ClientConnector` rather than `Ssl` directly, as it manages that configuration.
pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
where S: Read + Write
{
@@ -1123,6 +1207,11 @@ impl Ssl {
}
/// Creates an SSL/TLS server operating over the provided stream.
+ ///
+ /// # Warning
+ ///
+ /// OpenSSL's default configuration is insecure. It is highly recommended to use
+ /// `ServerConnector` rather than `Ssl` directly, as it manages that configuration.
pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
where S: Read + Write
{
@@ -1153,6 +1242,8 @@ impl Ssl {
/// An error or intermediate state after a TLS handshake attempt.
#[derive(Debug)]
pub enum HandshakeError<S> {
+ /// Setup failed.
+ SetupFailure(ErrorStack),
/// The handshake failed.
Failure(MidHandshakeSslStream<S>),
/// The handshake was interrupted midway through.
@@ -1162,6 +1253,7 @@ pub enum HandshakeError<S> {
impl<S: Any + fmt::Debug> stderror::Error for HandshakeError<S> {
fn description(&self) -> &str {
match *self {
+ HandshakeError::SetupFailure(_) => "stream setup failed",
HandshakeError::Failure(_) => "the handshake failed",
HandshakeError::Interrupted(_) => "the handshake was interrupted",
}
@@ -1169,6 +1261,7 @@ impl<S: Any + fmt::Debug> stderror::Error for HandshakeError<S> {
fn cause(&self) -> Option<&stderror::Error> {
match *self {
+ HandshakeError::SetupFailure(ref e) => Some(e),
HandshakeError::Failure(ref s) | HandshakeError::Interrupted(ref s) => Some(s.error()),
}
}
@@ -1178,6 +1271,7 @@ impl<S: Any + fmt::Debug> fmt::Display for HandshakeError<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(f.write_str(stderror::Error::description(self)));
match *self {
+ HandshakeError::SetupFailure(ref e) => try!(write!(f, ": {}", e)),
HandshakeError::Failure(ref s) | HandshakeError::Interrupted(ref s) => {
try!(write!(f, ": {}", s.error()));
if let Some(err) = s.ssl().verify_result() {
@@ -1189,6 +1283,12 @@ impl<S: Any + fmt::Debug> fmt::Display for HandshakeError<S> {
}
}
+impl<S> From<ErrorStack> for HandshakeError<S> {
+ fn from(e: ErrorStack) -> HandshakeError<S> {
+ HandshakeError::SetupFailure(e)
+ }
+}
+
/// An SSL stream midway through the handshake process.
#[derive(Debug)]
pub struct MidHandshakeSslStream<S> {