mirror of
https://github.com/fafhrd91/actix-net
synced 2024-11-24 00:01:11 +01:00
Rustls v0.21 support (#480)
This commit is contained in:
parent
6ce8307060
commit
0bc310a656
@ -15,9 +15,11 @@ ci-check-linux = "hack --workspace --feature-powerset check --tests --examples"
|
|||||||
|
|
||||||
# tests avoiding io-uring feature
|
# tests avoiding io-uring feature
|
||||||
ci-test = "hack --feature-powerset --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
|
ci-test = "hack --feature-powerset --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
|
||||||
|
ci-test-rustls-020 = "hack --feature-powerset --exclude-features=io-uring,rustls-0_21 test --lib --tests --no-fail-fast -- --nocapture"
|
||||||
|
ci-test-rustls-021 = "hack --feature-powerset --exclude-features=io-uring,rustls-0_20 test --lib --tests --no-fail-fast -- --nocapture"
|
||||||
|
|
||||||
# tests avoiding io-uring feature on Windows
|
# tests avoiding io-uring feature on Windows
|
||||||
ci-test-win = "hack --feature-powerset --depth 2 --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
|
ci-test-win = "hack --feature-powerset --depth=2 --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
|
||||||
|
|
||||||
# test with io-uring feature
|
# test with io-uring feature
|
||||||
ci-test-linux = "hack --feature-powerset test --lib --tests --no-fail-fast -- --nocapture"
|
ci-test-linux = "hack --feature-powerset --exclude-features=rustls-0_20 test --lib --tests --no-fail-fast -- --nocapture"
|
||||||
|
16
.github/workflows/ci-post-merge.yml
vendored
16
.github/workflows/ci-post-merge.yml
vendored
@ -16,6 +16,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
# prettier-ignore
|
||||||
target:
|
target:
|
||||||
- { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu }
|
- { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu }
|
||||||
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
||||||
@ -37,6 +38,10 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Free Disk Space
|
||||||
|
if: matrix.target.os == 'ubuntu-latest'
|
||||||
|
run: ./scripts/free-disk-space.sh
|
||||||
|
|
||||||
- name: Install OpenSSL
|
- name: Install OpenSSL
|
||||||
if: matrix.target.os == 'windows-latest'
|
if: matrix.target.os == 'windows-latest'
|
||||||
run: choco install openssl -y --forcex64 --no-progress
|
run: choco install openssl -y --forcex64 --no-progress
|
||||||
@ -83,8 +88,15 @@ jobs:
|
|||||||
run: cargo ci-test
|
run: cargo ci-test
|
||||||
- name: tests
|
- name: tests
|
||||||
if: matrix.target.os == 'ubuntu-latest'
|
if: matrix.target.os == 'ubuntu-latest'
|
||||||
run: |
|
run: >-
|
||||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux"
|
sudo bash -c "
|
||||||
|
ulimit -Sl 512
|
||||||
|
&& ulimit -Hl 512
|
||||||
|
&& PATH=$PATH:/usr/share/rust/.cargo/bin
|
||||||
|
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-020
|
||||||
|
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-021
|
||||||
|
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux
|
||||||
|
"
|
||||||
|
|
||||||
- name: Clear the cargo caches
|
- name: Clear the cargo caches
|
||||||
run: |
|
run: |
|
||||||
|
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@ -16,6 +16,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
# prettier-ignore
|
||||||
target:
|
target:
|
||||||
- { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu }
|
- { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu }
|
||||||
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
||||||
@ -99,8 +100,15 @@ jobs:
|
|||||||
run: cargo ci-test-win
|
run: cargo ci-test-win
|
||||||
- name: tests
|
- name: tests
|
||||||
if: matrix.target.os == 'ubuntu-latest'
|
if: matrix.target.os == 'ubuntu-latest'
|
||||||
run: |
|
run: >-
|
||||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux"
|
sudo bash -c "
|
||||||
|
ulimit -Sl 512
|
||||||
|
&& ulimit -Hl 512
|
||||||
|
&& PATH=$PATH:/usr/share/rust/.cargo/bin
|
||||||
|
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-020
|
||||||
|
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-021
|
||||||
|
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux
|
||||||
|
"
|
||||||
|
|
||||||
- name: Clear the cargo caches
|
- name: Clear the cargo caches
|
||||||
run: |
|
run: |
|
||||||
|
@ -15,6 +15,7 @@ members = [
|
|||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.65"
|
rust-version = "1.65"
|
||||||
|
|
||||||
|
@ -625,6 +625,7 @@ impl Future for ServerWorker {
|
|||||||
self.poll(cx)
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
WorkerState::Restarting(ref mut restart) => {
|
WorkerState::Restarting(ref mut restart) => {
|
||||||
let factory_id = restart.factory_id;
|
let factory_id = restart.factory_id;
|
||||||
let token = restart.token;
|
let token = restart.token;
|
||||||
@ -649,6 +650,7 @@ impl Future for ServerWorker {
|
|||||||
|
|
||||||
self.poll(cx)
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkerState::Shutdown(ref mut shutdown) => {
|
WorkerState::Shutdown(ref mut shutdown) => {
|
||||||
// drop all pending connections in rx channel.
|
// drop all pending connections in rx channel.
|
||||||
while let Poll::Ready(Some(conn)) = this.conn_rx.poll_recv(cx) {
|
while let Poll::Ready(Some(conn)) = this.conn_rx.poll_recv(cx) {
|
||||||
@ -682,6 +684,7 @@ impl Future for ServerWorker {
|
|||||||
shutdown.timer.as_mut().poll(cx)
|
shutdown.timer.as_mut().poll(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// actively poll stream and handle worker command
|
// actively poll stream and handle worker command
|
||||||
WorkerState::Available => loop {
|
WorkerState::Available => loop {
|
||||||
match this.check_readiness(cx) {
|
match this.check_readiness(cx) {
|
||||||
|
@ -1,40 +1,43 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2023-xx-xx
|
## Unreleased
|
||||||
|
|
||||||
|
- Support Rustls v0.21.
|
||||||
|
- Added `{accept, connect}::rustls_0_21` modules.
|
||||||
|
- Added `{accept, connect}::rustls_0_20` alias for `{accept, connect}::rustls` modules.
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||||
|
|
||||||
## 3.0.4 - 2022-03-15
|
## 3.0.4
|
||||||
|
|
||||||
- Logs emitted now use the `tracing` crate with `log` compatibility. [#451]
|
- Logs emitted now use the `tracing` crate with `log` compatibility. [#451]
|
||||||
|
|
||||||
[#451]: https://github.com/actix/actix-net/pull/451
|
[#451]: https://github.com/actix/actix-net/pull/451
|
||||||
|
|
||||||
## 3.0.3 - 2022-02-15
|
## 3.0.3
|
||||||
|
|
||||||
- No significant changes since `3.0.2`.
|
- No significant changes since `3.0.2`.
|
||||||
|
|
||||||
## 3.0.2 - 2022-01-28
|
## 3.0.2
|
||||||
|
|
||||||
- Expose `connect::Connection::new`. [#439]
|
- Expose `connect::Connection::new`. [#439]
|
||||||
|
|
||||||
[#439]: https://github.com/actix/actix-net/pull/439
|
[#439]: https://github.com/actix/actix-net/pull/439
|
||||||
|
|
||||||
## 3.0.1 - 2022-01-11
|
## 3.0.1
|
||||||
|
|
||||||
- No significant changes since `3.0.0`.
|
- No significant changes since `3.0.0`.
|
||||||
|
|
||||||
## 3.0.0 - 2021-12-26
|
## 3.0.0
|
||||||
|
|
||||||
- No significant changes since `3.0.0-rc.2`.
|
- No significant changes since `3.0.0-rc.2`.
|
||||||
|
|
||||||
## 3.0.0-rc.2 - 2021-12-10
|
## 3.0.0-rc.2
|
||||||
|
|
||||||
- Re-export `openssl::SslConnectorBuilder` in `connect::openssl::reexports`. [#429]
|
- Re-export `openssl::SslConnectorBuilder` in `connect::openssl::reexports`. [#429]
|
||||||
|
|
||||||
[#429]: https://github.com/actix/actix-net/pull/429
|
[#429]: https://github.com/actix/actix-net/pull/429
|
||||||
|
|
||||||
## 3.0.0-rc.1 - 2021-11-29
|
## 3.0.0-rc.1
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
@ -72,7 +75,7 @@
|
|||||||
[#422]: https://github.com/actix/actix-net/pull/422
|
[#422]: https://github.com/actix/actix-net/pull/422
|
||||||
[#423]: https://github.com/actix/actix-net/pull/423
|
[#423]: https://github.com/actix/actix-net/pull/423
|
||||||
|
|
||||||
## 3.0.0-beta.9 - 2021-11-22
|
## 3.0.0-beta.9
|
||||||
|
|
||||||
- Add configurable timeout for accepting TLS connection. [#393]
|
- Add configurable timeout for accepting TLS connection. [#393]
|
||||||
- Added `TlsError::Timeout` variant. [#393]
|
- Added `TlsError::Timeout` variant. [#393]
|
||||||
@ -82,20 +85,20 @@
|
|||||||
[#393]: https://github.com/actix/actix-net/pull/393
|
[#393]: https://github.com/actix/actix-net/pull/393
|
||||||
[#420]: https://github.com/actix/actix-net/pull/420
|
[#420]: https://github.com/actix/actix-net/pull/420
|
||||||
|
|
||||||
## 3.0.0-beta.8 - 2021-11-15
|
## 3.0.0-beta.8
|
||||||
|
|
||||||
- Add `Connect::request` for getting a reference to the connection request. [#415]
|
- Add `Connect::request` for getting a reference to the connection request. [#415]
|
||||||
|
|
||||||
[#415]: https://github.com/actix/actix-net/pull/415
|
[#415]: https://github.com/actix/actix-net/pull/415
|
||||||
|
|
||||||
## 3.0.0-beta.7 - 2021-10-20
|
## 3.0.0-beta.7
|
||||||
|
|
||||||
- Add `webpki_roots_cert_store()` to get rustls compatible webpki roots cert store. [#401]
|
- Add `webpki_roots_cert_store()` to get rustls compatible webpki roots cert store. [#401]
|
||||||
- Alias `connect::ssl` to `connect::tls`. [#401]
|
- Alias `connect::ssl` to `connect::tls`. [#401]
|
||||||
|
|
||||||
[#401]: https://github.com/actix/actix-net/pull/401
|
[#401]: https://github.com/actix/actix-net/pull/401
|
||||||
|
|
||||||
## 3.0.0-beta.6 - 2021-10-19
|
## 3.0.0-beta.6
|
||||||
|
|
||||||
- Update `tokio-rustls` to `0.23` which uses `rustls` `0.20`. [#396]
|
- Update `tokio-rustls` to `0.23` which uses `rustls` `0.20`. [#396]
|
||||||
- Removed a re-export of `Session` from `rustls` as it no longer exist. [#396]
|
- Removed a re-export of `Session` from `rustls` as it no longer exist. [#396]
|
||||||
@ -103,7 +106,7 @@
|
|||||||
|
|
||||||
[#396]: https://github.com/actix/actix-net/pull/396
|
[#396]: https://github.com/actix/actix-net/pull/396
|
||||||
|
|
||||||
## 3.0.0-beta.5 - 2021-03-29
|
## 3.0.0-beta.5
|
||||||
|
|
||||||
- Changed `connect::ssl::rustls::RustlsConnectorService` to return error when `DNSNameRef` generation failed instead of panic. [#296]
|
- Changed `connect::ssl::rustls::RustlsConnectorService` to return error when `DNSNameRef` generation failed instead of panic. [#296]
|
||||||
- Remove `connect::ssl::openssl::OpensslConnectServiceFactory`. [#297]
|
- Remove `connect::ssl::openssl::OpensslConnectServiceFactory`. [#297]
|
||||||
@ -117,7 +120,7 @@
|
|||||||
[#297]: https://github.com/actix/actix-net/pull/297
|
[#297]: https://github.com/actix/actix-net/pull/297
|
||||||
[#299]: https://github.com/actix/actix-net/pull/299
|
[#299]: https://github.com/actix/actix-net/pull/299
|
||||||
|
|
||||||
## 3.0.0-beta.4 - 2021-02-24
|
## 3.0.0-beta.4
|
||||||
|
|
||||||
- Rename `accept::openssl::{SslStream => TlsStream}`.
|
- Rename `accept::openssl::{SslStream => TlsStream}`.
|
||||||
- Add `connect::Connect::set_local_addr` to attach local `IpAddr`. [#282]
|
- Add `connect::Connect::set_local_addr` to attach local `IpAddr`. [#282]
|
||||||
@ -125,7 +128,7 @@
|
|||||||
|
|
||||||
[#282]: https://github.com/actix/actix-net/pull/282
|
[#282]: https://github.com/actix/actix-net/pull/282
|
||||||
|
|
||||||
## 3.0.0-beta.3 - 2021-02-06
|
## 3.0.0-beta.3
|
||||||
|
|
||||||
- Remove `trust-dns-proto` and `trust-dns-resolver`. [#248]
|
- Remove `trust-dns-proto` and `trust-dns-resolver`. [#248]
|
||||||
- Use `std::net::ToSocketAddrs` as simple and basic default resolver. [#248]
|
- Use `std::net::ToSocketAddrs` as simple and basic default resolver. [#248]
|
||||||
@ -139,13 +142,13 @@
|
|||||||
[#248]: https://github.com/actix/actix-net/pull/248
|
[#248]: https://github.com/actix/actix-net/pull/248
|
||||||
[#273]: https://github.com/actix/actix-net/pull/273
|
[#273]: https://github.com/actix/actix-net/pull/273
|
||||||
|
|
||||||
## 3.0.0-beta.2 - 2022-xx-xx
|
## 3.0.0-beta.2
|
||||||
|
|
||||||
- Depend on stable trust-dns packages. [#204]
|
- Depend on stable trust-dns packages. [#204]
|
||||||
|
|
||||||
[#204]: https://github.com/actix/actix-net/pull/204
|
[#204]: https://github.com/actix/actix-net/pull/204
|
||||||
|
|
||||||
## 3.0.0-beta.1 - 2020-12-29
|
## 3.0.0-beta.1
|
||||||
|
|
||||||
- Move acceptors under `accept` module. [#238]
|
- Move acceptors under `accept` module. [#238]
|
||||||
- Merge `actix-connect` crate under `connect` module. [#238]
|
- Merge `actix-connect` crate under `connect` module. [#238]
|
||||||
@ -153,7 +156,7 @@
|
|||||||
|
|
||||||
[#238]: https://github.com/actix/actix-net/pull/238
|
[#238]: https://github.com/actix/actix-net/pull/238
|
||||||
|
|
||||||
## 2.0.0 - 2020-09-03
|
## 2.0.0
|
||||||
|
|
||||||
- `nativetls::NativeTlsAcceptor` is renamed to `nativetls::Acceptor`.
|
- `nativetls::NativeTlsAcceptor` is renamed to `nativetls::Acceptor`.
|
||||||
- Where possible, "SSL" terminology is replaced with "TLS".
|
- Where possible, "SSL" terminology is replaced with "TLS".
|
||||||
@ -161,28 +164,28 @@
|
|||||||
- `TlsError::Ssl` enum variant is renamed to `TlsError::Tls`.
|
- `TlsError::Ssl` enum variant is renamed to `TlsError::Tls`.
|
||||||
- `max_concurrent_ssl_connect` is renamed to `max_concurrent_tls_connect`.
|
- `max_concurrent_ssl_connect` is renamed to `max_concurrent_tls_connect`.
|
||||||
|
|
||||||
## 2.0.0-alpha.2 - 2020-08-17
|
## 2.0.0-alpha.2
|
||||||
|
|
||||||
- Update `rustls` dependency to 0.18
|
- Update `rustls` dependency to 0.18
|
||||||
- Update `tokio-rustls` dependency to 0.14
|
- Update `tokio-rustls` dependency to 0.14
|
||||||
- Update `webpki-roots` dependency to 0.20
|
- Update `webpki-roots` dependency to 0.20
|
||||||
|
|
||||||
## [2.0.0-alpha.1] - 2020-03-03
|
## [2.0.0-alpha.1]
|
||||||
|
|
||||||
- Update `rustls` dependency to 0.17
|
- Update `rustls` dependency to 0.17
|
||||||
- Update `tokio-rustls` dependency to 0.13
|
- Update `tokio-rustls` dependency to 0.13
|
||||||
- Update `webpki-roots` dependency to 0.19
|
- Update `webpki-roots` dependency to 0.19
|
||||||
|
|
||||||
## [1.0.0] - 2019-12-11
|
## [1.0.0]
|
||||||
|
|
||||||
- 1.0.0 release
|
- 1.0.0 release
|
||||||
|
|
||||||
## [1.0.0-alpha.3] - 2019-12-07
|
## [1.0.0-alpha.3]
|
||||||
|
|
||||||
- Migrate to tokio 0.2
|
- Migrate to tokio 0.2
|
||||||
- Enable rustls acceptor service
|
- Enable rustls acceptor service
|
||||||
- Enable native-tls acceptor service
|
- Enable native-tls acceptor service
|
||||||
|
|
||||||
## [1.0.0-alpha.1] - 2019-12-02
|
## [1.0.0-alpha.1]
|
||||||
|
|
||||||
- Split openssl acceptor from actix-server package
|
- Split openssl acceptor from actix-server package
|
||||||
|
@ -9,7 +9,7 @@ description = "TLS acceptor and connector services for Actix ecosystem"
|
|||||||
keywords = ["network", "tls", "ssl", "async", "transport"]
|
keywords = ["network", "tls", "ssl", "async", "transport"]
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
categories = ["network-programming", "asynchronous", "cryptography"]
|
categories = ["network-programming", "asynchronous", "cryptography"]
|
||||||
license = "MIT OR Apache-2.0"
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
@ -29,8 +29,14 @@ connect = []
|
|||||||
# use openssl impls
|
# use openssl impls
|
||||||
openssl = ["tls-openssl", "tokio-openssl"]
|
openssl = ["tls-openssl", "tokio-openssl"]
|
||||||
|
|
||||||
# use rustls impls
|
# alias for backwards compat
|
||||||
rustls = ["tokio-rustls", "webpki-roots"]
|
rustls = ["rustls-0_20"]
|
||||||
|
|
||||||
|
# use rustls v0.20 impls
|
||||||
|
rustls-0_20 = ["tokio-rustls-023", "webpki-roots-022"]
|
||||||
|
|
||||||
|
# use rustls v0.21 impls
|
||||||
|
rustls-0_21 = ["tokio-rustls-024", "webpki-roots-025"]
|
||||||
|
|
||||||
# use native-tls impls
|
# use native-tls impls
|
||||||
native-tls = ["tokio-native-tls"]
|
native-tls = ["tokio-native-tls"]
|
||||||
@ -57,9 +63,13 @@ http = { version = "0.2.3", optional = true }
|
|||||||
tls-openssl = { package = "openssl", version = "0.10.48", optional = true }
|
tls-openssl = { package = "openssl", version = "0.10.48", optional = true }
|
||||||
tokio-openssl = { version = "0.6", optional = true }
|
tokio-openssl = { version = "0.6", optional = true }
|
||||||
|
|
||||||
# rustls
|
# rustls v0.20
|
||||||
tokio-rustls = { version = "0.23", optional = true }
|
tokio-rustls-023 = { package = "tokio-rustls", version = "0.23", optional = true }
|
||||||
webpki-roots = { version = "0.22", optional = true }
|
webpki-roots-022 = { package = "webpki-roots", version = "0.22", optional = true }
|
||||||
|
|
||||||
|
# rustls v0.21
|
||||||
|
tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", optional = true }
|
||||||
|
webpki-roots-025 = { package = "webpki-roots", version = "0.25", optional = true }
|
||||||
|
|
||||||
# native-tls
|
# native-tls
|
||||||
tokio-native-tls = { version = "0.3", optional = true }
|
tokio-native-tls = { version = "0.3", optional = true }
|
||||||
@ -72,11 +82,11 @@ bytes = "1"
|
|||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
futures-util = { version = "0.3.17", default-features = false, features = ["sink"] }
|
futures-util = { version = "0.3.17", default-features = false, features = ["sink"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
rcgen = "0.10"
|
rcgen = "0.11"
|
||||||
rustls-pemfile = "1"
|
rustls-pemfile = "1"
|
||||||
tokio-rustls = { version = "0.23", features = ["dangerous_configuration"] }
|
tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", features = ["dangerous_configuration"] }
|
||||||
trust-dns-resolver = "0.22"
|
trust-dns-resolver = "0.23"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "accept-rustls"
|
name = "accept-rustls"
|
||||||
required-features = ["accept", "rustls"]
|
required-features = ["accept", "rustls-0_21"]
|
||||||
|
@ -17,12 +17,13 @@
|
|||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
// this `use` is only exists because of how we have organised the crate
|
// this `use` is only exists because of how we have organised the crate
|
||||||
// it is not necessary for your actual code; you should import from `rustls` directly
|
// it is not necessary for your actual code; you should import from `rustls` normally
|
||||||
use tokio_rustls::rustls;
|
use tokio_rustls_024::rustls;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{self, BufReader},
|
io::{self, BufReader},
|
||||||
|
path::PathBuf,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicUsize, Ordering},
|
atomic::{AtomicUsize, Ordering},
|
||||||
Arc,
|
Arc,
|
||||||
@ -32,7 +33,7 @@ use std::{
|
|||||||
use actix_rt::net::TcpStream;
|
use actix_rt::net::TcpStream;
|
||||||
use actix_server::Server;
|
use actix_server::Server;
|
||||||
use actix_service::ServiceFactoryExt as _;
|
use actix_service::ServiceFactoryExt as _;
|
||||||
use actix_tls::accept::rustls::{Acceptor as RustlsAcceptor, TlsStream};
|
use actix_tls::accept::rustls_0_21::{Acceptor as RustlsAcceptor, TlsStream};
|
||||||
use futures_util::future::ok;
|
use futures_util::future::ok;
|
||||||
use rustls::{server::ServerConfig, Certificate, PrivateKey};
|
use rustls::{server::ServerConfig, Certificate, PrivateKey};
|
||||||
use rustls_pemfile::{certs, rsa_private_keys};
|
use rustls_pemfile::{certs, rsa_private_keys};
|
||||||
@ -42,9 +43,16 @@ use tracing::info;
|
|||||||
async fn main() -> io::Result<()> {
|
async fn main() -> io::Result<()> {
|
||||||
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
|
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
|
||||||
|
|
||||||
|
let root_path = env!("CARGO_MANIFEST_DIR")
|
||||||
|
.parse::<PathBuf>()
|
||||||
|
.unwrap()
|
||||||
|
.join("examples");
|
||||||
|
let cert_path = root_path.clone().join("cert.pem");
|
||||||
|
let key_path = root_path.clone().join("key.pem");
|
||||||
|
|
||||||
// Load TLS key and cert files
|
// Load TLS key and cert files
|
||||||
let cert_file = &mut BufReader::new(File::open("./examples/cert.pem").unwrap());
|
let cert_file = &mut BufReader::new(File::open(cert_path).unwrap());
|
||||||
let key_file = &mut BufReader::new(File::open("./examples/key.pem").unwrap());
|
let key_file = &mut BufReader::new(File::open(key_path).unwrap());
|
||||||
|
|
||||||
let cert_chain = certs(cert_file)
|
let cert_chain = certs(cert_file)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -64,7 +72,7 @@ async fn main() -> io::Result<()> {
|
|||||||
let count = Arc::new(AtomicUsize::new(0));
|
let count = Arc::new(AtomicUsize::new(0));
|
||||||
|
|
||||||
let addr = ("127.0.0.1", 8443);
|
let addr = ("127.0.0.1", 8443);
|
||||||
info!("starting server on port: {}", &addr.0);
|
info!("starting server at: {addr:?}");
|
||||||
|
|
||||||
Server::build()
|
Server::build()
|
||||||
.bind("tls-example", addr, move || {
|
.bind("tls-example", addr, move || {
|
||||||
|
@ -12,15 +12,27 @@ use actix_utils::counter::Counter;
|
|||||||
#[cfg(feature = "openssl")]
|
#[cfg(feature = "openssl")]
|
||||||
pub mod openssl;
|
pub mod openssl;
|
||||||
|
|
||||||
#[cfg(feature = "rustls")]
|
#[cfg(feature = "rustls-0_20")]
|
||||||
pub mod rustls;
|
pub mod rustls_0_20;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[cfg(feature = "rustls-0_20")]
|
||||||
|
pub use rustls_0_20 as rustls;
|
||||||
|
|
||||||
|
#[cfg(feature = "rustls-0_21")]
|
||||||
|
pub mod rustls_0_21;
|
||||||
|
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
pub mod native_tls;
|
pub mod native_tls;
|
||||||
|
|
||||||
pub(crate) static MAX_CONN: AtomicUsize = AtomicUsize::new(256);
|
pub(crate) static MAX_CONN: AtomicUsize = AtomicUsize::new(256);
|
||||||
|
|
||||||
#[cfg(any(feature = "openssl", feature = "rustls", feature = "native-tls"))]
|
#[cfg(any(
|
||||||
|
feature = "openssl",
|
||||||
|
feature = "rustls-0_20",
|
||||||
|
feature = "rustls-0_21",
|
||||||
|
feature = "native-tls",
|
||||||
|
))]
|
||||||
pub(crate) const DEFAULT_TLS_HANDSHAKE_TIMEOUT: std::time::Duration =
|
pub(crate) const DEFAULT_TLS_HANDSHAKE_TIMEOUT: std::time::Duration =
|
||||||
std::time::Duration::from_secs(3);
|
std::time::Duration::from_secs(3);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//! `rustls` based TLS connection acceptor service.
|
//! `rustls` v0.20 based TLS connection acceptor service.
|
||||||
//!
|
//!
|
||||||
//! See [`Acceptor`] for main service factory docs.
|
//! See [`Acceptor`] for main service factory docs.
|
||||||
|
|
||||||
@ -24,13 +24,14 @@ use actix_utils::{
|
|||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
use tokio_rustls::{rustls::ServerConfig, Accept, TlsAcceptor};
|
use tokio_rustls::{rustls::ServerConfig, Accept, TlsAcceptor};
|
||||||
|
use tokio_rustls_023 as tokio_rustls;
|
||||||
|
|
||||||
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||||
|
|
||||||
pub mod reexports {
|
pub mod reexports {
|
||||||
//! Re-exports from `rustls` that are useful for acceptors.
|
//! Re-exports from `rustls` that are useful for acceptors.
|
||||||
|
|
||||||
pub use tokio_rustls::rustls::ServerConfig;
|
pub use tokio_rustls_023::rustls::ServerConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
|
/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
|
198
actix-tls/src/accept/rustls_0_21.rs
Normal file
198
actix-tls/src/accept/rustls_0_21.rs
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
//! `rustls` v0.21 based TLS connection acceptor service.
|
||||||
|
//!
|
||||||
|
//! See [`Acceptor`] for main service factory docs.
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
convert::Infallible,
|
||||||
|
future::Future,
|
||||||
|
io::{self, IoSlice},
|
||||||
|
pin::Pin,
|
||||||
|
sync::Arc,
|
||||||
|
task::{Context, Poll},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use actix_rt::{
|
||||||
|
net::{ActixStream, Ready},
|
||||||
|
time::{sleep, Sleep},
|
||||||
|
};
|
||||||
|
use actix_service::{Service, ServiceFactory};
|
||||||
|
use actix_utils::{
|
||||||
|
counter::{Counter, CounterGuard},
|
||||||
|
future::{ready, Ready as FutReady},
|
||||||
|
};
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
|
use tokio_rustls::{rustls::ServerConfig, Accept, TlsAcceptor};
|
||||||
|
use tokio_rustls_024 as tokio_rustls;
|
||||||
|
|
||||||
|
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||||
|
|
||||||
|
pub mod reexports {
|
||||||
|
//! Re-exports from `rustls` that are useful for acceptors.
|
||||||
|
|
||||||
|
pub use tokio_rustls_024::rustls::ServerConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
|
||||||
|
pub struct TlsStream<IO>(tokio_rustls::server::TlsStream<IO>);
|
||||||
|
|
||||||
|
impl_more::impl_from!(<IO> in tokio_rustls::server::TlsStream<IO> => TlsStream<IO>);
|
||||||
|
impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_rustls::server::TlsStream<IO>);
|
||||||
|
|
||||||
|
impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
|
||||||
|
fn poll_read(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &mut ReadBuf<'_>,
|
||||||
|
) -> Poll<io::Result<()>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_read(cx, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
|
||||||
|
fn poll_write(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> Poll<io::Result<usize>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_write(cx, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_flush(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_shutdown(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_write_vectored(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
bufs: &[IoSlice<'_>],
|
||||||
|
) -> Poll<io::Result<usize>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_write_vectored(cx, bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_write_vectored(&self) -> bool {
|
||||||
|
(**self).is_write_vectored()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> ActixStream for TlsStream<IO> {
|
||||||
|
fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
|
||||||
|
IO::poll_read_ready((**self).get_ref().0, cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
|
||||||
|
IO::poll_write_ready((**self).get_ref().0, cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Accept TLS connections via the `rustls` crate.
|
||||||
|
pub struct Acceptor {
|
||||||
|
config: Arc<ServerConfig>,
|
||||||
|
handshake_timeout: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Acceptor {
|
||||||
|
/// Constructs `rustls` based acceptor service factory.
|
||||||
|
pub fn new(config: ServerConfig) -> Self {
|
||||||
|
Acceptor {
|
||||||
|
config: Arc::new(config),
|
||||||
|
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Limit the amount of time that the acceptor will wait for a TLS handshake to complete.
|
||||||
|
///
|
||||||
|
/// Default timeout is 3 seconds.
|
||||||
|
pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
|
||||||
|
self.handshake_timeout = handshake_timeout;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Acceptor {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
config: self.config.clone(),
|
||||||
|
handshake_timeout: self.handshake_timeout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> ServiceFactory<IO> for Acceptor {
|
||||||
|
type Response = TlsStream<IO>;
|
||||||
|
type Error = TlsError<io::Error, Infallible>;
|
||||||
|
type Config = ();
|
||||||
|
type Service = AcceptorService;
|
||||||
|
type InitError = ();
|
||||||
|
type Future = FutReady<Result<Self::Service, Self::InitError>>;
|
||||||
|
|
||||||
|
fn new_service(&self, _: ()) -> Self::Future {
|
||||||
|
let res = MAX_CONN_COUNTER.with(|conns| {
|
||||||
|
Ok(AcceptorService {
|
||||||
|
acceptor: self.config.clone().into(),
|
||||||
|
conns: conns.clone(),
|
||||||
|
handshake_timeout: self.handshake_timeout,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
ready(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rustls based acceptor service.
|
||||||
|
pub struct AcceptorService {
|
||||||
|
acceptor: TlsAcceptor,
|
||||||
|
conns: Counter,
|
||||||
|
handshake_timeout: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> Service<IO> for AcceptorService {
|
||||||
|
type Response = TlsStream<IO>;
|
||||||
|
type Error = TlsError<io::Error, Infallible>;
|
||||||
|
type Future = AcceptFut<IO>;
|
||||||
|
|
||||||
|
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
if self.conns.available(cx) {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, req: IO) -> Self::Future {
|
||||||
|
AcceptFut {
|
||||||
|
fut: self.acceptor.accept(req),
|
||||||
|
timeout: sleep(self.handshake_timeout),
|
||||||
|
_guard: self.conns.get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_project! {
|
||||||
|
/// Accept future for Rustls service.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct AcceptFut<IO: ActixStream> {
|
||||||
|
fut: Accept<IO>,
|
||||||
|
#[pin]
|
||||||
|
timeout: Sleep,
|
||||||
|
_guard: CounterGuard,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> Future for AcceptFut<IO> {
|
||||||
|
type Output = Result<TlsStream<IO>, TlsError<io::Error, Infallible>>;
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let mut this = self.project();
|
||||||
|
match Pin::new(&mut this.fut).poll(cx) {
|
||||||
|
Poll::Ready(Ok(stream)) => Poll::Ready(Ok(TlsStream(stream))),
|
||||||
|
Poll::Ready(Err(err)) => Poll::Ready(Err(TlsError::Tls(err))),
|
||||||
|
Poll::Pending => this.timeout.poll(cx).map(|_| Err(TlsError::Timeout)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,8 +27,15 @@ mod uri;
|
|||||||
#[cfg(feature = "openssl")]
|
#[cfg(feature = "openssl")]
|
||||||
pub mod openssl;
|
pub mod openssl;
|
||||||
|
|
||||||
#[cfg(feature = "rustls")]
|
#[cfg(feature = "rustls-0_20")]
|
||||||
pub mod rustls;
|
pub mod rustls_0_20;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[cfg(feature = "rustls-0_20")]
|
||||||
|
pub use rustls_0_20 as rustls;
|
||||||
|
|
||||||
|
#[cfg(feature = "rustls-0_21")]
|
||||||
|
pub mod rustls_0_21;
|
||||||
|
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
pub mod native_tls;
|
pub mod native_tls;
|
||||||
|
@ -20,22 +20,21 @@ use tokio_rustls::{
|
|||||||
rustls::{client::ServerName, ClientConfig, OwnedTrustAnchor, RootCertStore},
|
rustls::{client::ServerName, ClientConfig, OwnedTrustAnchor, RootCertStore},
|
||||||
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
||||||
};
|
};
|
||||||
use tracing::trace;
|
use tokio_rustls_023 as tokio_rustls;
|
||||||
use webpki_roots::TLS_SERVER_ROOTS;
|
|
||||||
|
|
||||||
use crate::connect::{Connection, Host};
|
use crate::connect::{Connection, Host};
|
||||||
|
|
||||||
pub mod reexports {
|
pub mod reexports {
|
||||||
//! Re-exports from `rustls` and `webpki_roots` that are useful for connectors.
|
//! Re-exports from `rustls` and `webpki_roots` that are useful for connectors.
|
||||||
|
|
||||||
pub use tokio_rustls::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
pub use tokio_rustls_023::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||||
pub use webpki_roots::TLS_SERVER_ROOTS;
|
pub use webpki_roots_022::TLS_SERVER_ROOTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
||||||
pub fn webpki_roots_cert_store() -> RootCertStore {
|
pub fn webpki_roots_cert_store() -> RootCertStore {
|
||||||
let mut root_certs = RootCertStore::empty();
|
let mut root_certs = RootCertStore::empty();
|
||||||
for cert in TLS_SERVER_ROOTS.0 {
|
for cert in webpki_roots_022::TLS_SERVER_ROOTS.0 {
|
||||||
let cert = OwnedTrustAnchor::from_subject_spki_name_constraints(
|
let cert = OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||||
cert.subject,
|
cert.subject,
|
||||||
cert.spki,
|
cert.spki,
|
||||||
@ -102,12 +101,13 @@ where
|
|||||||
actix_service::always_ready!();
|
actix_service::always_ready!();
|
||||||
|
|
||||||
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
|
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
|
||||||
trace!("TLS handshake start for: {:?}", connection.hostname());
|
tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
|
||||||
let (stream, connection) = connection.replace_io(());
|
let (stream, connection) = connection.replace_io(());
|
||||||
|
|
||||||
match ServerName::try_from(connection.hostname()) {
|
match ServerName::try_from(connection.hostname()) {
|
||||||
Ok(host) => ConnectFut::Future {
|
Ok(host) => ConnectFut::Future {
|
||||||
connect: RustlsTlsConnector::from(self.connector.clone()).connect(host, stream),
|
connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
|
||||||
|
.connect(host, stream),
|
||||||
connection: Some(connection),
|
connection: Some(connection),
|
||||||
},
|
},
|
||||||
Err(_) => ConnectFut::InvalidDns,
|
Err(_) => ConnectFut::InvalidDns,
|
||||||
@ -117,6 +117,7 @@ where
|
|||||||
|
|
||||||
/// Connect future for Rustls service.
|
/// Connect future for Rustls service.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
pub enum ConnectFut<R, IO> {
|
pub enum ConnectFut<R, IO> {
|
||||||
/// See issue <https://github.com/briansmith/webpki/issues/54>
|
/// See issue <https://github.com/briansmith/webpki/issues/54>
|
||||||
InvalidDns,
|
InvalidDns,
|
||||||
@ -131,17 +132,23 @@ where
|
|||||||
R: Host,
|
R: Host,
|
||||||
IO: ActixStream,
|
IO: ActixStream,
|
||||||
{
|
{
|
||||||
type Output = Result<Connection<R, AsyncTlsStream<IO>>, io::Error>;
|
type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
|
||||||
|
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
match self.get_mut() {
|
match self.get_mut() {
|
||||||
Self::InvalidDns => Poll::Ready(Err(
|
Self::InvalidDns => Poll::Ready(Err(io::Error::new(
|
||||||
io::Error::new(io::ErrorKind::Other, "rustls currently only handles hostname-based connections. See https://github.com/briansmith/webpki/issues/54")
|
io::ErrorKind::Other,
|
||||||
)),
|
"Rustls v0.20 can only handle hostname-based connections. Enable the `rustls-0_21` \
|
||||||
Self::Future { connect, connection } => {
|
feature and use the Rustls v0.21 utilities to gain this feature.",
|
||||||
|
))),
|
||||||
|
|
||||||
|
Self::Future {
|
||||||
|
connect,
|
||||||
|
connection,
|
||||||
|
} => {
|
||||||
let stream = ready!(Pin::new(connect).poll(cx))?;
|
let stream = ready!(Pin::new(connect).poll(cx))?;
|
||||||
let connection = connection.take().unwrap();
|
let connection = connection.take().unwrap();
|
||||||
trace!("TLS handshake success: {:?}", connection.hostname());
|
tracing::trace!("TLS handshake success: {:?}", connection.hostname());
|
||||||
Poll::Ready(Ok(connection.replace_io(stream).1))
|
Poll::Ready(Ok(connection.replace_io(stream).1))
|
||||||
}
|
}
|
||||||
}
|
}
|
154
actix-tls/src/connect/rustls_0_21.rs
Normal file
154
actix-tls/src/connect/rustls_0_21.rs
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
//! Rustls based connector service.
|
||||||
|
//!
|
||||||
|
//! See [`TlsConnector`] for main connector service factory docs.
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
convert::TryFrom,
|
||||||
|
future::Future,
|
||||||
|
io,
|
||||||
|
pin::Pin,
|
||||||
|
sync::Arc,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
|
||||||
|
use actix_rt::net::ActixStream;
|
||||||
|
use actix_service::{Service, ServiceFactory};
|
||||||
|
use actix_utils::future::{ok, Ready};
|
||||||
|
use futures_core::ready;
|
||||||
|
use tokio_rustls::{
|
||||||
|
client::TlsStream as AsyncTlsStream,
|
||||||
|
rustls::{client::ServerName, ClientConfig, OwnedTrustAnchor, RootCertStore},
|
||||||
|
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
||||||
|
};
|
||||||
|
use tokio_rustls_024 as tokio_rustls;
|
||||||
|
|
||||||
|
use crate::connect::{Connection, Host};
|
||||||
|
|
||||||
|
pub mod reexports {
|
||||||
|
//! Re-exports from `rustls` and `webpki_roots` that are useful for connectors.
|
||||||
|
|
||||||
|
pub use tokio_rustls_024::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||||
|
pub use webpki_roots_025::TLS_SERVER_ROOTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
||||||
|
pub fn webpki_roots_cert_store() -> RootCertStore {
|
||||||
|
let mut root_certs = RootCertStore::empty();
|
||||||
|
for cert in webpki_roots_025::TLS_SERVER_ROOTS {
|
||||||
|
let cert = OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||||
|
cert.subject,
|
||||||
|
cert.spki,
|
||||||
|
cert.name_constraints,
|
||||||
|
);
|
||||||
|
let certs = vec![cert].into_iter();
|
||||||
|
root_certs.add_trust_anchors(certs);
|
||||||
|
}
|
||||||
|
root_certs
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connector service factory using `rustls`.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TlsConnector {
|
||||||
|
connector: Arc<ClientConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlsConnector {
|
||||||
|
/// Constructs new connector service factory from a `rustls` client configuration.
|
||||||
|
pub fn new(connector: Arc<ClientConfig>) -> Self {
|
||||||
|
TlsConnector { connector }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructs new connector service from a `rustls` client configuration.
|
||||||
|
pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService {
|
||||||
|
TlsConnectorService { connector }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
|
||||||
|
where
|
||||||
|
R: Host,
|
||||||
|
IO: ActixStream + 'static,
|
||||||
|
{
|
||||||
|
type Response = Connection<R, AsyncTlsStream<IO>>;
|
||||||
|
type Error = io::Error;
|
||||||
|
type Config = ();
|
||||||
|
type Service = TlsConnectorService;
|
||||||
|
type InitError = ();
|
||||||
|
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||||
|
|
||||||
|
fn new_service(&self, _: ()) -> Self::Future {
|
||||||
|
ok(TlsConnectorService {
|
||||||
|
connector: self.connector.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connector service using `rustls`.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TlsConnectorService {
|
||||||
|
connector: Arc<ClientConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
|
||||||
|
where
|
||||||
|
R: Host,
|
||||||
|
IO: ActixStream,
|
||||||
|
{
|
||||||
|
type Response = Connection<R, AsyncTlsStream<IO>>;
|
||||||
|
type Error = io::Error;
|
||||||
|
type Future = ConnectFut<R, IO>;
|
||||||
|
|
||||||
|
actix_service::always_ready!();
|
||||||
|
|
||||||
|
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
|
||||||
|
tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
|
||||||
|
let (stream, connection) = connection.replace_io(());
|
||||||
|
|
||||||
|
match ServerName::try_from(connection.hostname()) {
|
||||||
|
Ok(host) => ConnectFut::Future {
|
||||||
|
connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
|
||||||
|
.connect(host, stream),
|
||||||
|
connection: Some(connection),
|
||||||
|
},
|
||||||
|
Err(_) => ConnectFut::InvalidServerName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connect future for Rustls service.
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
pub enum ConnectFut<R, IO> {
|
||||||
|
InvalidServerName,
|
||||||
|
Future {
|
||||||
|
connect: RustlsConnect<IO>,
|
||||||
|
connection: Option<Connection<R, ()>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, IO> Future for ConnectFut<R, IO>
|
||||||
|
where
|
||||||
|
R: Host,
|
||||||
|
IO: ActixStream,
|
||||||
|
{
|
||||||
|
type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
match self.get_mut() {
|
||||||
|
Self::InvalidServerName => Poll::Ready(Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"connection parameters specified invalid server name",
|
||||||
|
))),
|
||||||
|
|
||||||
|
Self::Future {
|
||||||
|
connect,
|
||||||
|
connection,
|
||||||
|
} => {
|
||||||
|
let stream = ready!(Pin::new(connect).poll(cx))?;
|
||||||
|
let connection = connection.take().unwrap();
|
||||||
|
tracing::trace!("TLS handshake success: {:?}", connection.hostname());
|
||||||
|
Poll::Ready(Ok(connection.replace_io(stream).1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
#![cfg(all(
|
#![cfg(all(
|
||||||
feature = "accept",
|
feature = "accept",
|
||||||
feature = "connect",
|
feature = "connect",
|
||||||
feature = "rustls",
|
feature = "rustls-0_21",
|
||||||
feature = "openssl"
|
feature = "openssl"
|
||||||
))]
|
))]
|
||||||
|
|
||||||
@ -15,6 +15,7 @@ use actix_service::ServiceFactoryExt as _;
|
|||||||
use actix_tls::accept::openssl::{Acceptor, TlsStream};
|
use actix_tls::accept::openssl::{Acceptor, TlsStream};
|
||||||
use actix_utils::future::ok;
|
use actix_utils::future::ok;
|
||||||
use tokio_rustls::rustls::{Certificate, ClientConfig, RootCertStore, ServerName};
|
use tokio_rustls::rustls::{Certificate, ClientConfig, RootCertStore, ServerName};
|
||||||
|
use tokio_rustls_024 as tokio_rustls;
|
||||||
|
|
||||||
fn new_cert_and_key() -> (String, String) {
|
fn new_cert_and_key() -> (String, String) {
|
||||||
let cert =
|
let cert =
|
||||||
@ -49,7 +50,7 @@ fn openssl_acceptor(cert: String, key: String) -> tls_openssl::ssl::SslAcceptor
|
|||||||
mod danger {
|
mod danger {
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use tokio_rustls::rustls::{
|
use tokio_rustls_024::rustls::{
|
||||||
self,
|
self,
|
||||||
client::{ServerCertVerified, ServerCertVerifier},
|
client::{ServerCertVerified, ServerCertVerifier},
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#![cfg(all(
|
#![cfg(all(
|
||||||
feature = "accept",
|
feature = "accept",
|
||||||
feature = "connect",
|
feature = "connect",
|
||||||
feature = "rustls",
|
feature = "rustls-0_21",
|
||||||
feature = "openssl"
|
feature = "openssl"
|
||||||
))]
|
))]
|
||||||
|
|
||||||
@ -15,13 +15,14 @@ use actix_rt::net::TcpStream;
|
|||||||
use actix_server::TestServer;
|
use actix_server::TestServer;
|
||||||
use actix_service::ServiceFactoryExt as _;
|
use actix_service::ServiceFactoryExt as _;
|
||||||
use actix_tls::{
|
use actix_tls::{
|
||||||
accept::rustls::{Acceptor, TlsStream},
|
accept::rustls_0_21::{Acceptor, TlsStream},
|
||||||
connect::openssl::reexports::SslConnector,
|
connect::openssl::reexports::SslConnector,
|
||||||
};
|
};
|
||||||
use actix_utils::future::ok;
|
use actix_utils::future::ok;
|
||||||
use rustls_pemfile::{certs, pkcs8_private_keys};
|
use rustls_pemfile::{certs, pkcs8_private_keys};
|
||||||
use tls_openssl::ssl::SslVerifyMode;
|
use tls_openssl::ssl::SslVerifyMode;
|
||||||
use tokio_rustls::rustls::{self, Certificate, PrivateKey, ServerConfig};
|
use tokio_rustls::rustls::{self, Certificate, PrivateKey, ServerConfig};
|
||||||
|
use tokio_rustls_024 as tokio_rustls;
|
||||||
|
|
||||||
fn new_cert_and_key() -> (String, String) {
|
fn new_cert_and_key() -> (String, String) {
|
||||||
let cert =
|
let cert =
|
||||||
|
@ -30,7 +30,7 @@ async fn test_string() {
|
|||||||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "rustls")]
|
#[cfg(feature = "rustls-0_21")]
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_rustls_string() {
|
async fn test_rustls_string() {
|
||||||
let srv = TestServer::start(|| {
|
let srv = TestServer::start(|| {
|
||||||
@ -114,7 +114,7 @@ async fn test_openssl_uri() {
|
|||||||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "rustls", feature = "uri"))]
|
#[cfg(all(feature = "rustls-0_21", feature = "uri"))]
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_rustls_uri() {
|
async fn test_rustls_uri() {
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
@ -29,7 +29,7 @@ impl Counter {
|
|||||||
|
|
||||||
/// Returns true if counter is below capacity. Otherwise, register to wake task when it is.
|
/// Returns true if counter is below capacity. Otherwise, register to wake task when it is.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn available(&self, cx: &mut task::Context<'_>) -> bool {
|
pub fn available(&self, cx: &task::Context<'_>) -> bool {
|
||||||
self.0.available(cx)
|
self.0.available(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ impl CounterInner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn available(&self, cx: &mut task::Context<'_>) -> bool {
|
fn available(&self, cx: &task::Context<'_>) -> bool {
|
||||||
if self.count.get() < self.capacity {
|
if self.count.get() < self.capacity {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
@ -62,6 +62,7 @@ where
|
|||||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
// SAFETY: we are not moving out of the pinned field
|
// SAFETY: we are not moving out of the pinned field
|
||||||
// see https://github.com/rust-lang/rust/pull/102737
|
// see https://github.com/rust-lang/rust/pull/102737
|
||||||
|
#[allow(clippy::needless_borrow)]
|
||||||
(unsafe { &mut self.get_unchecked_mut().f })(cx)
|
(unsafe { &mut self.get_unchecked_mut().f })(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user