Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OpenSSL support #21

Merged
merged 1 commit into from
Mar 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ jobs:
- tokio-net
- rustls
- native-tls
- openssl
- rt
- hyper-h1
- hyper-h2
- rustls,native-tls
- rustls,native-tls,openssl
- tokio-net,rt,rustls
- tokio-net,native-tls
steps:
Expand Down
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

## Upcoming 0.5.1

### Added

- Support for [`openssl`](https://github.com/sfackler/rust-openssl)

### Fixed

- Fixed compilation on non-unix environments, where tokio-net doesn't include unix sockets
- `SpawningHandshakes` will abort the tasks for pending connections when the linked futures are dropped. This should allow timeouts to cause the connectionto be closed.


## 0.5.0 - 2022-03-20

### Added
Expand All @@ -29,7 +32,7 @@

### Added

- Added [TlsListener::replace_acceptor()] function to allow replacing the listener certificate at runtime.
- Added `TlsListener::replace_acceptor()` function to allow replacing the listener certificate at runtime.

## 0.4.1 - 2022-03-09

Expand Down
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "tls-listener"
description = "wrap incoming Stream of connections in TLS"
version = "0.5.0"
version = "0.5.1"
authors = ["Thayne McCombs <[email protected]>"]
repository = "https://github.com/tmccombs/tls-listener"
edition = "2018"
Expand All @@ -11,6 +11,7 @@ license = "Apache-2.0"
default = ["tokio-net"]
rustls = ["tokio-rustls"]
native-tls = ["tokio-native-tls"]
openssl = ["tokio-openssl", "openssl_impl"]
rt = ["tokio/rt"]

tokio-net = ["tokio/net"]
Expand All @@ -25,6 +26,8 @@ thiserror = "1.0.30"
tokio = { version = "1.0", features = ["time"] }
tokio-native-tls = { version = "0.3.0", optional = true }
tokio-rustls = { version = "0.23.0", optional = true }
tokio-openssl = { version = "0.6.3", optional = true }
openssl_impl = { package = "openssl", version = "0.10.32", optional = true }

[dev-dependencies]
hyper = { version = "0.14.1", features = ["http1", "stream"] }
Expand Down Expand Up @@ -56,5 +59,5 @@ path = "examples/http-low-level.rs"
required-features = ["hyper-h1"]

[package.metadata.docs.rs]
features = ["rustls", "native-tls", "hyper-h1", "hyper-h2"]
features = ["rustls", "native-tls", "openssl", "hyper-h1", "hyper-h2", "rt"]
rustdoc-args = ["--cfg", "docsrs"]
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ one of the `hyper-h1` or `hyper-h2` features).

See examples for examples of usage.

You must enable either one of the `rustls` or `native-tls` features depending on which implementation you would
like to use.
You must enable either one of the `rustls`, `native-tls`, or `openssl` features depending on which implementation you
would like to use.
13 changes: 11 additions & 2 deletions examples/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@ use tls_listener::{AsyncAccept, TlsListener};
use tokio::io::{copy, split};
use tokio::net::{TcpListener, TcpStream};
use tokio::signal::ctrl_c;
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]

#[cfg(all(
feature = "native-tls",
not(any(feature = "rustls", feature = "openssl"))
))]
use tokio_native_tls::TlsStream;
#[cfg(all(
feature = "openssl",
not(any(feature = "rustls", feature = "native-tls"))
))]
use tokio_openssl::SslStream as TlsStream;
#[cfg(feature = "rustls")]
use tokio_rustls::server::TlsStream;

Expand All @@ -22,7 +31,7 @@ async fn handle_stream(stream: TlsStream<TcpStream>) {
}

/// For example try opening and closing a connection with:
/// `echo "Q" | openssl s_client -connect host:port`
/// `echo "Q" | openssl s_client -connect localhost:3000`
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr: SocketAddr = ([127, 0, 0, 1], 3000).into();
Expand Down
2 changes: 2 additions & 0 deletions examples/http-low-level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use std::convert::Infallible;
mod tls_config;
use tls_config::tls_acceptor;

/// For example try:
/// `curl https://localhost:3000 -k`
#[tokio::main(flavor = "current_thread")]
async fn main() {
let addr = ([127, 0, 0, 1], 3000).into();
Expand Down
23 changes: 21 additions & 2 deletions examples/tls_config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mod cert {
pub const CERT: &[u8] = include_bytes!("local.cert");
pub const PKEY: &[u8] = include_bytes!("local.key");
}
#[cfg(feature = "native-tls")]
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
const PFX: &[u8] = include_bytes!("local.pfx");

#[cfg(feature = "rustls")]
Expand All @@ -24,10 +24,29 @@ pub fn tls_acceptor() -> tokio_rustls::TlsAcceptor {
.into()
}

#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
#[cfg(all(
feature = "native-tls",
not(any(feature = "rustls", feature = "openssl"))
))]
pub fn tls_acceptor() -> tokio_native_tls::TlsAcceptor {
use tokio_native_tls::native_tls::{Identity, TlsAcceptor};

let identity = Identity::from_pkcs12(PFX, "").unwrap();
TlsAcceptor::builder(identity).build().unwrap().into()
}

#[cfg(all(
feature = "openssl",
not(any(feature = "rustls", feature = "native-tls"))
))]
pub fn tls_acceptor() -> openssl_impl::ssl::SslContext {
use openssl_impl::ssl::{SslContext, SslFiletype, SslMethod};
let mut builder = SslContext::builder(SslMethod::tls_server()).unwrap();
builder
.set_certificate_file("./examples/tls_config/local.cert", SslFiletype::ASN1)
.unwrap();
builder
.set_private_key_file("./examples/tls_config/local.key", SslFiletype::ASN1)
.unwrap();
builder.build()
}
29 changes: 29 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,35 @@ where
}
}

#[cfg(feature = "openssl")]
impl<C> AsyncTls<C> for openssl_impl::ssl::SslContext
where
C: AsyncRead + AsyncWrite + Unpin + Send + 'static,
{
type Stream = tokio_openssl::SslStream<C>;
type Error = openssl_impl::ssl::Error;
type AcceptFuture = Pin<Box<dyn Future<Output = Result<Self::Stream, Self::Error>> + Send>>;

fn accept(&self, conn: C) -> Self::AcceptFuture {
let ssl = match openssl_impl::ssl::Ssl::new(self) {
Ok(s) => s,
Err(e) => {
return Box::pin(futures_util::future::err(e.into()));
}
};
let mut stream = match tokio_openssl::SslStream::new(ssl, conn) {
Ok(s) => s,
Err(e) => {
return Box::pin(futures_util::future::err(e.into()));
}
};
Box::pin(async move {
Pin::new(&mut stream).accept().await?;
Ok(stream)
})
}
}

impl<T> Builder<T> {
/// Set the maximum number of concurrent handshakes.
///
Expand Down