Skip to content

Commit 2125aca

Browse files
authored
Rustls v0.22 support (#3275)
1 parent b1eb57a commit 2125aca

File tree

24 files changed

+719
-196
lines changed

24 files changed

+719
-196
lines changed

.cargo/config.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[alias]
2-
lint = "clippy --workspace --tests --examples --bins -- -Dclippy::todo"
3-
lint-all = "clippy --workspace --all-features --tests --examples --bins -- -Dclippy::todo"
2+
lint = "clippy --workspace --all-targets -- -Dclippy::todo"
3+
lint-all = "clippy --workspace --all-features --all-targets -- -Dclippy::todo"
44

55
# lib checking
66
ci-check-min = "hack --workspace check --no-default-features"

.github/workflows/ci-post-merge.yml

+10-13
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,22 @@ jobs:
3232

3333
- name: Install OpenSSL
3434
if: matrix.target.os == 'windows-latest'
35-
run: choco install openssl -y --forcex64 --no-progress
36-
- name: Set OpenSSL dir in env
37-
if: matrix.target.os == 'windows-latest'
35+
shell: bash
3836
run: |
39-
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append
40-
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append
37+
set -e
38+
choco install openssl --version=1.1.1.2100 -y --no-progress
39+
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV
40+
echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV
4141
4242
- name: Install Rust (${{ matrix.version.name }})
4343
uses: actions-rust-lang/[email protected]
4444
with:
4545
toolchain: ${{ matrix.version.version }}
4646

47-
- name: Install cargo-hack
47+
- name: Install cargo-hack and cargo-ci-cache-clean
4848
uses: taiki-e/[email protected]
4949
with:
50-
tool: cargo-hack
50+
tool: cargo-hack,cargo-ci-cache-clean
5151

5252
- name: check minimal
5353
run: cargo ci-check-min
@@ -57,10 +57,12 @@ jobs:
5757

5858
- name: tests
5959
timeout-minutes: 60
60+
shell: bash
6061
run: |
62+
set -e
6163
cargo test --lib --tests -p=actix-router --all-features
6264
cargo test --lib --tests -p=actix-http --all-features
63-
cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls
65+
cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,rustls-0_22,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls
6466
cargo test --lib --tests -p=actix-web-codegen --all-features
6567
cargo test --lib --tests -p=awc --all-features
6668
cargo test --lib --tests -p=actix-http-test --all-features
@@ -69,11 +71,6 @@ jobs:
6971
cargo test --lib --tests -p=actix-multipart --all-features
7072
cargo test --lib --tests -p=actix-web-actors --all-features
7173
72-
- name: Install cargo-ci-cache-clean
73-
uses: taiki-e/[email protected]
74-
with:
75-
tool: cargo-ci-cache-clean
76-
7774
- name: CI cache clean
7875
run: cargo-ci-cache-clean
7976

.github/workflows/ci.yml

+10-13
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,22 @@ jobs:
3737

3838
- name: Install OpenSSL
3939
if: matrix.target.os == 'windows-latest'
40-
run: choco install openssl -y --forcex64 --no-progress --version=3.2.1
41-
- name: Set OpenSSL dir in env
42-
if: matrix.target.os == 'windows-latest'
40+
shell: bash
4341
run: |
44-
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append
45-
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append
42+
set -e
43+
choco install openssl --version=1.1.1.2100 -y --no-progress
44+
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV
45+
echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV
4646
4747
- name: Install Rust (${{ matrix.version.name }})
4848
uses: actions-rust-lang/[email protected]
4949
with:
5050
toolchain: ${{ matrix.version.version }}
5151

52-
- name: Install cargo-hack
52+
- name: Install cargo-hack and cargo-ci-cache-clean
5353
uses: taiki-e/[email protected]
5454
with:
55-
tool: cargo-hack
55+
tool: cargo-hack,cargo-ci-cache-clean
5656

5757
- name: workaround MSRV issues
5858
if: matrix.version.name == 'msrv'
@@ -71,10 +71,12 @@ jobs:
7171

7272
- name: tests
7373
timeout-minutes: 60
74+
shell: bash
7475
run: |
76+
set -e
7577
cargo test --lib --tests -p=actix-router --all-features
7678
cargo test --lib --tests -p=actix-http --all-features
77-
cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls
79+
cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,rustls-0_22,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls
7880
cargo test --lib --tests -p=actix-web-codegen --all-features
7981
cargo test --lib --tests -p=awc --all-features
8082
cargo test --lib --tests -p=actix-http-test --all-features
@@ -83,11 +85,6 @@ jobs:
8385
cargo test --lib --tests -p=actix-multipart --all-features
8486
cargo test --lib --tests -p=actix-web-actors --all-features
8587
86-
- name: Install cargo-ci-cache-clean
87-
uses: taiki-e/[email protected]
88-
with:
89-
tool: cargo-ci-cache-clean
90-
9188
- name: CI cache clean
9289
run: cargo-ci-cache-clean
9390

actix-files/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ mod tests {
568568
assert_eq!(bytes, data);
569569
}
570570

571+
#[cfg(not(target_os = "windows"))]
571572
#[actix_rt::test]
572573
async fn test_static_files_with_special_characters() {
573574
// Create the file we want to test against ad-hoc. We can't check it in as otherwise

actix-http/CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### Added
66

7+
- Add `rustls-0_22` crate feature.
8+
- Add `{h1::H1Service, h2::H2Service, HttpService}::rustls_0_22()` and `HttpService::rustls_0_22_with_config()` service constructors.
79
- Implement `From<&HeaderMap>` for `http::HeaderMap`.
810

911
## 3.5.1

actix-http/Cargo.toml

+22-9
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,18 @@ edition.workspace = true
2020
rust-version.workspace = true
2121

2222
[package.metadata.docs.rs]
23-
# features that docs.rs will build with
24-
features = ["http2", "ws", "openssl", "rustls-0_20", "rustls-0_21", "compress-brotli", "compress-gzip", "compress-zstd"]
23+
rustdoc-args = ["--cfg", "docsrs"]
24+
features = [
25+
"http2",
26+
"ws",
27+
"openssl",
28+
"rustls-0_20",
29+
"rustls-0_21",
30+
"rustls-0_22",
31+
"compress-brotli",
32+
"compress-gzip",
33+
"compress-zstd",
34+
]
2535

2636
[lib]
2737
name = "actix_http"
@@ -53,6 +63,9 @@ rustls-0_20 = ["actix-tls/accept", "actix-tls/rustls-0_20"]
5363
# TLS via Rustls v0.21
5464
rustls-0_21 = ["actix-tls/accept", "actix-tls/rustls-0_21"]
5565

66+
# TLS via Rustls v0.22
67+
rustls-0_22 = ["actix-tls/accept", "actix-tls/rustls-0_22"]
68+
5669
# Compression codecs
5770
compress-brotli = ["__compress", "brotli"]
5871
compress-gzip = ["__compress", "flate2"]
@@ -98,7 +111,7 @@ rand = { version = "0.8", optional = true }
98111
sha1 = { version = "0.10", optional = true }
99112

100113
# openssl/rustls
101-
actix-tls = { version = "3.1", default-features = false, optional = true }
114+
actix-tls = { version = "3.3", default-features = false, optional = true }
102115

103116
# compress-*
104117
brotli = { version = "3.3.3", optional = true }
@@ -108,7 +121,7 @@ zstd = { version = "0.13", optional = true }
108121
[dev-dependencies]
109122
actix-http-test = { version = "3", features = ["openssl"] }
110123
actix-server = "2"
111-
actix-tls = { version = "3.1", features = ["openssl"] }
124+
actix-tls = { version = "3.3", features = ["openssl", "rustls-0_22-webpki-roots"] }
112125
actix-web = "4"
113126

114127
async-stream = "0.3"
@@ -117,24 +130,24 @@ env_logger = "0.10"
117130
futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] }
118131
memchr = "2.4"
119132
once_cell = "1.9"
120-
rcgen = "0.11"
133+
rcgen = "0.12"
121134
regex = "1.3"
122135
rustversion = "1"
123-
rustls-pemfile = "1"
136+
rustls-pemfile = "2"
124137
serde = { version = "1.0", features = ["derive"] }
125138
serde_json = "1.0"
126139
static_assertions = "1"
127140
tls-openssl = { package = "openssl", version = "0.10.55" }
128-
tls-rustls_021 = { package = "rustls", version = "0.21" }
141+
tls-rustls_022 = { package = "rustls", version = "0.22" }
129142
tokio = { version = "1.24.2", features = ["net", "rt", "macros"] }
130143

131144
[[example]]
132145
name = "ws"
133-
required-features = ["ws", "rustls-0_21"]
146+
required-features = ["ws", "rustls-0_22"]
134147

135148
[[example]]
136149
name = "tls_rustls"
137-
required-features = ["http2", "rustls-0_21"]
150+
required-features = ["http2", "rustls-0_22"]
138151

139152
[[bench]]
140153
name = "response-body-compression"

actix-http/examples/tls_rustls.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
//! Protocol: HTTP/1.1
1313
//! ```
1414
15-
extern crate tls_rustls_021 as rustls;
15+
extern crate tls_rustls_022 as rustls;
1616

1717
use std::io;
1818

@@ -36,7 +36,7 @@ async fn main() -> io::Result<()> {
3636
);
3737
ok::<_, Error>(Response::ok().set_body(body))
3838
})
39-
.rustls_021(rustls_config())
39+
.rustls_0_22(rustls_config())
4040
})?
4141
.run()
4242
.await
@@ -51,16 +51,18 @@ fn rustls_config() -> rustls::ServerConfig {
5151
let key_file = &mut io::BufReader::new(key_file.as_bytes());
5252

5353
let cert_chain = rustls_pemfile::certs(cert_file)
54-
.unwrap()
55-
.into_iter()
56-
.map(rustls::Certificate)
57-
.collect();
58-
let mut keys = rustls_pemfile::pkcs8_private_keys(key_file).unwrap();
54+
.collect::<Result<Vec<_>, _>>()
55+
.unwrap();
56+
let mut keys = rustls_pemfile::pkcs8_private_keys(key_file)
57+
.collect::<Result<Vec<_>, _>>()
58+
.unwrap();
5959

6060
let mut config = rustls::ServerConfig::builder()
61-
.with_safe_defaults()
6261
.with_no_client_auth()
63-
.with_single_cert(cert_chain, rustls::PrivateKey(keys.remove(0)))
62+
.with_single_cert(
63+
cert_chain,
64+
rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0)),
65+
)
6466
.unwrap();
6567

6668
const H1_ALPN: &[u8] = b"http/1.1";

actix-http/examples/ws.rs

+10-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Sets up a WebSocket server over TCP and TLS.
22
//! Sends a heartbeat message every 4 seconds but does not respond to any incoming frames.
33
4-
extern crate tls_rustls_021 as rustls;
4+
extern crate tls_rustls_022 as rustls;
55

66
use std::{
77
io,
@@ -30,7 +30,7 @@ async fn main() -> io::Result<()> {
3030
.bind("tls", ("127.0.0.1", 8443), || {
3131
HttpService::build()
3232
.finish(handler)
33-
.rustls_021(tls_config())
33+
.rustls_0_22(tls_config())
3434
})?
3535
.run()
3636
.await
@@ -85,7 +85,6 @@ impl Stream for Heartbeat {
8585
fn tls_config() -> rustls::ServerConfig {
8686
use std::io::BufReader;
8787

88-
use rustls::{Certificate, PrivateKey};
8988
use rustls_pemfile::{certs, pkcs8_private_keys};
9089

9190
let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap();
@@ -95,17 +94,17 @@ fn tls_config() -> rustls::ServerConfig {
9594
let cert_file = &mut BufReader::new(cert_file.as_bytes());
9695
let key_file = &mut BufReader::new(key_file.as_bytes());
9796

98-
let cert_chain = certs(cert_file)
99-
.unwrap()
100-
.into_iter()
101-
.map(Certificate)
102-
.collect();
103-
let mut keys = pkcs8_private_keys(key_file).unwrap();
97+
let cert_chain = certs(cert_file).collect::<Result<Vec<_>, _>>().unwrap();
98+
let mut keys = pkcs8_private_keys(key_file)
99+
.collect::<Result<Vec<_>, _>>()
100+
.unwrap();
104101

105102
let mut config = rustls::ServerConfig::builder()
106-
.with_safe_defaults()
107103
.with_no_client_auth()
108-
.with_single_cert(cert_chain, PrivateKey(keys.remove(0)))
104+
.with_single_cert(
105+
cert_chain,
106+
rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0)),
107+
)
109108
.unwrap();
110109

111110
config.alpn_protocols.push(b"http/1.1".to_vec());

actix-http/src/h1/service.rs

+63-2
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ mod openssl {
153153
}
154154

155155
#[cfg(feature = "rustls-0_20")]
156-
mod rustls_020 {
156+
mod rustls_0_20 {
157157
use std::io;
158158

159159
use actix_service::ServiceFactoryExt as _;
@@ -214,7 +214,7 @@ mod rustls_020 {
214214
}
215215

216216
#[cfg(feature = "rustls-0_21")]
217-
mod rustls_021 {
217+
mod rustls_0_21 {
218218
use std::io;
219219

220220
use actix_service::ServiceFactoryExt as _;
@@ -274,6 +274,67 @@ mod rustls_021 {
274274
}
275275
}
276276

277+
#[cfg(feature = "rustls-0_22")]
278+
mod rustls_0_22 {
279+
use std::io;
280+
281+
use actix_service::ServiceFactoryExt as _;
282+
use actix_tls::accept::{
283+
rustls_0_22::{reexports::ServerConfig, Acceptor, TlsStream},
284+
TlsError,
285+
};
286+
287+
use super::*;
288+
289+
impl<S, B, X, U> H1Service<TlsStream<TcpStream>, S, B, X, U>
290+
where
291+
S: ServiceFactory<Request, Config = ()>,
292+
S::Future: 'static,
293+
S::Error: Into<Response<BoxBody>>,
294+
S::InitError: fmt::Debug,
295+
S::Response: Into<Response<B>>,
296+
297+
B: MessageBody,
298+
299+
X: ServiceFactory<Request, Config = (), Response = Request>,
300+
X::Future: 'static,
301+
X::Error: Into<Response<BoxBody>>,
302+
X::InitError: fmt::Debug,
303+
304+
U: ServiceFactory<
305+
(Request, Framed<TlsStream<TcpStream>, Codec>),
306+
Config = (),
307+
Response = (),
308+
>,
309+
U::Future: 'static,
310+
U::Error: fmt::Display + Into<Response<BoxBody>>,
311+
U::InitError: fmt::Debug,
312+
{
313+
/// Create Rustls v0.22 based service.
314+
pub fn rustls_0_22(
315+
self,
316+
config: ServerConfig,
317+
) -> impl ServiceFactory<
318+
TcpStream,
319+
Config = (),
320+
Response = (),
321+
Error = TlsError<io::Error, DispatchError>,
322+
InitError = (),
323+
> {
324+
Acceptor::new(config)
325+
.map_init_err(|_| {
326+
unreachable!("TLS acceptor service factory does not error on init")
327+
})
328+
.map_err(TlsError::into_service_error)
329+
.map(|io: TlsStream<TcpStream>| {
330+
let peer_addr = io.get_ref().0.peer_addr().ok();
331+
(io, peer_addr)
332+
})
333+
.and_then(self.map_err(TlsError::Service))
334+
}
335+
}
336+
}
337+
277338
impl<T, S, B, X, U> H1Service<T, S, B, X, U>
278339
where
279340
S: ServiceFactory<Request, Config = ()>,

0 commit comments

Comments
 (0)