chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

View File

@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"6a3c46057c2d51e1dd4a5aa67d57f5ab4db91657e86417f5e42583e289754bd3",".github/dependabot.yml":"2c0c80aabf4b7ebbd09306ac2a3b0b4506085db3f39edbe5e7da6dcea97d4115",".github/workflows/build.yml":"954d16f8a95b0770047208ed7cc9657c1e701b12ec4892a2a7cbe47453c788a4",".rustfmt.toml":"079483fb72cf5e4d45fcf021e6fdab3c30a88b941b139f7df3a552f84e5e0455","Cargo.lock":"38200193af24441e4dc8ed8dabbc8c3adbb4f0a49588ac178d5f5072663654a6","Cargo.toml":"d835791214e048ded7c6deddc663b628e7e077daa67ce24fc9843e7999938fd0","Cargo.toml.orig":"4a0120f81c4207801e29e7be002c91d98dc2eaba7c98ac0f98bf1c292df29a51","LICENSE":"d1ef92123fc699442e1e8d971fe84921947efc8d9a1249ab037f1e661a972a6d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-ISC":"7cfafc877eccc46c0e346ccbaa5c51bb6b894d2b818e617d970211e232785ad4","LICENSE-MIT":"709e3175b4212f7b13aa93971c9f62ff8c69ec45ad8c6532a7e0c41d7a7d6f8c","README.md":"9124a22136f3b0fa82f22896a25989b120bf05be197e0f110cdf408f63aaf5fd","RELEASING.md":"01733c2c7ba9966525a0df69ba0c634d5accdeb3aaca466410134fbd6a8e6c03","examples/client.rs":"79e10c996aac0483109d9495d338570c64e60097c22a73778db0476fea3edd7c","examples/openssl.cnf":"cfa19da355f64e20f0ed90deae3a4cea3fc644bab79955e555b6801d028a81b9","examples/refresh-certificates.sh":"00a421b85e88f794926ce8faf645b1ceeae65029675cf039b3c21d6735dd37ee","examples/sample.pem":"61696c7bd7f3f700d4befb40f5d335adff3f98d8bcf07b76a06387de4faa51e9","examples/sample.rsa":"bca5b33775fffe53d6e4bcdc3d8b33fcfb9cd4cc40bb6e38a0c2761a84c64fcf","examples/server.rs":"024556b773fb46dc084b9aa6c739f2725c5fdacfcf8b94fbb6549b164c9711b6","src/config.rs":"b249782e789e18928fe454f0ac08180256d24adbb3ca40a0cf469ed8ed404df8","src/connector.rs":"d796974eecf557428a0f0dbceaea28b437d91bbfda2d3bf6c89f77157dfc50af","src/connector/builder.rs":"1b5c3424dee4a0fe8d5ae0a1c882b732c209df4892e6756191a06d825e2647c7","src/lib.rs":"4f55e7914274119123eb563033cc7a8bfc2536d9191f8ddd20943e3c44bf90e2","src/stream.rs":"49039649158136eec6e0dec37bb4ab6459fd58cfe821f65b4a578da3e9f4e39a","tests/tests.rs":"f2421455609c402123a040f1699c168e855a3e55ac3c214dd400b00cf824350a"},"package":"e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"}

View File

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "aff7441ec40be7c334886f8807f32cccecb5adbe"
},
"path_in_vcs": ""
}

View File

@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: cargo
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly

View File

@@ -0,0 +1,182 @@
name: rustls
permissions:
contents: read
on:
push:
pull_request:
merge_group:
schedule:
- cron: '23 6 * * 5'
jobs:
build:
name: Build+test
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# test a bunch of toolchains on ubuntu
rust:
- stable
- beta
- nightly
os: [ubuntu-latest]
# but only stable on macos/windows (slower platforms)
include:
- os: macos-latest
rust: stable
- os: windows-latest
rust: stable
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install ${{ matrix.rust }} toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- name: Install NASM for aws-lc-rs on Windows
if: runner.os == 'Windows'
uses: ilammy/setup-nasm@v1
- name: Install ninja-build tool for aws-lc-fips-sys on Windows
if: runner.os == 'Windows'
uses: seanmiddleditch/gha-setup-ninja@v6
- name: cargo check (default features)
run: cargo check --all-targets
- name: cargo test (debug; default features)
run: cargo test
env:
RUST_BACKTRACE: 1
- name: cargo test (debug; native-tokio only)
run: cargo test --no-default-features --features native-tokio
env:
RUST_BACKTRACE: 1
- name: cargo test (debug; webpki-tokio only)
run: cargo test --no-default-features --features webpki-tokio
env:
RUST_BACKTRACE: 1
- name: cargo test (debug; defaults+ring)
run: cargo test --no-default-features --features ring,native-tokio,http1,tls12,logging
env:
RUST_BACKTRACE: 1
- name: cargo test (debug; all features)
if: runner.os == 'Linux'
run: cargo test --all-features
env:
RUST_BACKTRACE: 1
- name: cargo test (debug; all features, excluding FIPS)
if: runner.os != 'Linux'
run: cargo test --features aws-lc-rs,http1,http2,webpki-tokio,native-tokio,ring,tls12,logging
env:
RUST_BACKTRACE: 1
- name: cargo build (debug; no default features)
run: cargo build --no-default-features
- name: cargo test (debug; no default features; no run)
run: cargo test --no-default-features --no-run
- name: cargo test (release; no run)
run: cargo test --release --no-run
msrv:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.71"
- name: Check MSRV
run: cargo check --lib --all-features
semver:
name: Check semver compatibility
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Check semver
uses: obi1kenobi/cargo-semver-checks-action@v2
docs:
name: Check for documentation errors
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install rust toolchain
uses: dtolnay/rust-toolchain@nightly
- name: cargo doc (all features)
# keep features in sync with Cargo.toml `[package.metadata.docs.rs]` section
run: cargo doc --no-default-features --features http1,http2,webpki-tokio,native-tokio,ring,tls12,logging --no-deps
env:
RUSTDOCFLAGS: -Dwarnings
format:
name: Format
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- name: Check formatting
run: cargo fmt --all -- --check
clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- run: cargo clippy --all-features -- --deny warnings
features:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-hack
uses: taiki-e/install-action@cargo-hack
- name: Check feature powerset
run: cargo hack --no-dev-deps check --feature-powerset --depth 2

1
vendor/hyper-rustls/.rustfmt.toml vendored Normal file
View File

@@ -0,0 +1 @@
chain_width=40

1323
vendor/hyper-rustls/Cargo.lock generated vendored Normal file

File diff suppressed because it is too large Load Diff

171
vendor/hyper-rustls/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,171 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.71"
name = "hyper-rustls"
version = "0.27.7"
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Rustls+hyper integration for pure rust HTTPS"
homepage = "https://github.com/rustls/hyper-rustls"
documentation = "https://docs.rs/hyper-rustls/"
readme = "README.md"
license = "Apache-2.0 OR ISC OR MIT"
repository = "https://github.com/rustls/hyper-rustls"
[package.metadata.docs.rs]
features = [
"http1",
"http2",
"logging",
"native-tokio",
"ring",
"rustls-platform-verifier",
"tls12",
"webpki-tokio",
]
no-default-features = true
rustdoc-args = [
"--cfg",
"docsrs",
]
[features]
aws-lc-rs = ["rustls/aws_lc_rs"]
default = [
"native-tokio",
"http1",
"tls12",
"logging",
"aws-lc-rs",
]
fips = [
"aws-lc-rs",
"rustls/fips",
]
http1 = ["hyper-util/http1"]
http2 = ["hyper-util/http2"]
logging = [
"log",
"tokio-rustls/logging",
"rustls/logging",
]
native-tokio = ["rustls-native-certs"]
ring = ["rustls/ring"]
tls12 = [
"tokio-rustls/tls12",
"rustls/tls12",
]
webpki-tokio = ["webpki-roots"]
[lib]
name = "hyper_rustls"
path = "src/lib.rs"
[[example]]
name = "client"
path = "examples/client.rs"
required-features = [
"native-tokio",
"http1",
]
[[example]]
name = "server"
path = "examples/server.rs"
required-features = ["aws-lc-rs"]
[[test]]
name = "tests"
path = "tests/tests.rs"
[dependencies.http]
version = "1"
[dependencies.hyper]
version = "1"
default-features = false
[dependencies.hyper-util]
version = "0.1"
features = [
"client-legacy",
"tokio",
]
default-features = false
[dependencies.log]
version = "0.4.4"
optional = true
[dependencies.pki-types]
version = "1"
package = "rustls-pki-types"
[dependencies.rustls]
version = "0.23"
default-features = false
[dependencies.rustls-native-certs]
version = "0.8"
optional = true
[dependencies.rustls-platform-verifier]
version = "0.6"
optional = true
[dependencies.tokio]
version = "1.0"
[dependencies.tokio-rustls]
version = "0.26"
default-features = false
[dependencies.tower-service]
version = "0.3"
[dependencies.webpki-roots]
version = "1"
optional = true
[dev-dependencies.cfg-if]
version = "1"
[dev-dependencies.http-body-util]
version = "0.1"
[dev-dependencies.hyper-util]
version = "0.1"
features = ["server-auto"]
default-features = false
[dev-dependencies.rustls]
version = "0.23"
features = ["tls12"]
default-features = false
[dev-dependencies.rustls-pemfile]
version = "2"
[dev-dependencies.tokio]
version = "1.0"
features = [
"io-std",
"macros",
"net",
"rt-multi-thread",
]

10
vendor/hyper-rustls/LICENSE vendored Normal file
View File

@@ -0,0 +1,10 @@
hyper-rustls is distributed under the following three licenses:
- Apache License version 2.0.
- MIT license.
- ISC license.
These are included as LICENSE-APACHE, LICENSE-MIT and LICENSE-ISC
respectively. You may use this software under the terms of any
of these licenses, at your option.

201
vendor/hyper-rustls/LICENSE-APACHE vendored Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

15
vendor/hyper-rustls/LICENSE-ISC vendored Normal file
View File

@@ -0,0 +1,15 @@
ISC License (ISC)
Copyright (c) 2016, Joseph Birr-Pixton <jpixton@gmail.com>
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

25
vendor/hyper-rustls/LICENSE-MIT vendored Normal file
View File

@@ -0,0 +1,25 @@
Copyright (c) 2016 Joseph Birr-Pixton <jpixton@gmail.com>
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

64
vendor/hyper-rustls/README.md vendored Normal file
View File

@@ -0,0 +1,64 @@
# hyper-rustls
This is an integration between the [Rustls TLS stack](https://github.com/rustls/rustls) and the
[hyper HTTP library](https://github.com/hyperium/hyper).
[![Build Status](https://github.com/rustls/hyper-rustls/actions/workflows/build.yml/badge.svg)](https://github.com/rustls/hyper-rustls/actions)
[![Crate](https://img.shields.io/crates/v/hyper-rustls.svg)](https://crates.io/crates/hyper-rustls)
[![Documentation](https://docs.rs/hyper-rustls/badge.svg)](https://docs.rs/hyper-rustls)
# Release history
Release history can be found [on GitHub](https://github.com/rustls/hyper-rustls/releases).
# License
hyper-rustls is distributed under the following three licenses:
- Apache License version 2.0.
- MIT license.
- ISC license.
These are included as LICENSE-APACHE, LICENSE-MIT and LICENSE-ISC respectively. You may use this
software under the terms of any of these licenses, at your option.
## Running examples
### server
```bash
cargo run --example server
```
### client
```bash
cargo run --example client "https://docs.rs/hyper-rustls/latest/hyper_rustls/"
```
## Crate features
This crate exposes a number of features to add support for different portions of `hyper-util`,
`rustls`, and other dependencies.
| Feature flag | Enabled by default | Description |
| ------------ | ------------------ | ----------- |
| `aws-lc-rs` | **yes** | Enables use of the [AWS-LC][aws-lc-rs] backend for [`rustls`][rustls] |
| `http1` | **yes** | Enables HTTP/1 support in [`hyper-util`][hyper-util] |
| `http2` | **no** | Enables HTTP/2 support in [`hyper-util`][hyper-util] |
| `webpki-tokio` | **no** | Uses a compiled-in set of root certificates trusted by Mozilla (via [`webpki-roots`][webpki-roots]) |
| `native-tokio` | **yes** | Use the platform's native certificate store at runtime (via [`rustls-native-certs`][rustls-native-certs]) |
| `rustls-platform-verifier` | **no** | Use the operating system's verifier for certificate verification (via [`rustls-platform-verifier`][rustls-platform-verifier]) |
| `ring` | **no** | Enables use of the [`ring`][ring] backend for [`rustls`][rustls] |
| `tls12` | **yes** | Enables support for TLS 1.2 (only TLS 1.3 supported when disabled) |
| `logging` | **yes** | Enables logging of protocol-level diagnostics and errors via [`log`][log] |
| `fips` | **no** | Enables support for using a FIPS 140-3 compliant backend via AWS-LC (enables `aws-lc-rs` feature) |
[aws-lc-rs]: https://docs.rs/aws-lc-rs
[rustls]: https://docs.rs/rustls
[hyper-util]: https://docs.rs/hyper-util
[webpki-roots]: https://docs.rs/webpki-roots
[rustls-native-certs]: https://docs.rs/rustls-native-certs
[rustls-platform-verifier]: https://docs.rs/rustls-platform-verifier
[ring]: https://docs.rs/ring
[log]: https://docs.rs/log

26
vendor/hyper-rustls/RELEASING.md vendored Normal file
View File

@@ -0,0 +1,26 @@
# Making a hyper-rustls release
This is a checklist for steps to make before/after making a rustls release.
1. Attend to the README.md: this appears on crates.io for the release, and can't be edited after
the fact.
- Ensure the version has a good set of release notes. Move old release notes to OLDCHANGES.md
if this is getting excessively long.
- Write the version and date of the release.
2. Run `cargo update` followed by `cargo outdated`, to check if we have any
dependency updates which are not already automatically taken by their semver specs.
- If we do, take them if possible with separate commits (but there should've been
dependabot PRs submitted for these already.)
3. Now run `cargo test --all-features` to ensure our tests continue to pass with the
updated dependencies.
4. Update `Cargo.toml` to set the correct version.
5. Make a commit with the above changes, something like 'Prepare $VERSION'. This
should not contain functional changes: just versions numbers, and markdown changes.
6. Do a dry run: check `cargo publish --dry-run`
7. Push the above commit. Wait for CI to confirm it as green.
- Any red _should_ naturally block the release.
- If rustc nightly is broken, this _may_ be acceptable if the reason is understood
and does not point to a defect.
8. Tag the released version: `git tag -m '0.20.0' v/0.20.0`
9. Push the tag: `git push --tags`
10. Do the release: `cargo publish`.

105
vendor/hyper-rustls/examples/client.rs vendored Normal file
View File

@@ -0,0 +1,105 @@
//! Simple HTTPS GET client based on hyper-rustls
//!
//! First parameter is the mandatory URL to GET.
//! Second parameter is an optional path to CA store.
use http::Uri;
use http_body_util::{BodyExt, Empty};
use hyper::body::Bytes;
use hyper_rustls::ConfigBuilderExt;
use hyper_util::{client::legacy::Client, rt::TokioExecutor};
use rustls::RootCertStore;
use std::str::FromStr;
use std::{env, fs, io};
fn main() {
// Send GET request and inspect result, with proper error handling.
if let Err(e) = run_client() {
eprintln!("FAILED: {}", e);
std::process::exit(1);
}
}
fn error(err: String) -> io::Error {
io::Error::new(io::ErrorKind::Other, err)
}
#[tokio::main]
async fn run_client() -> io::Result<()> {
// Set a process wide default crypto provider.
#[cfg(feature = "ring")]
let _ = rustls::crypto::ring::default_provider().install_default();
#[cfg(feature = "aws-lc-rs")]
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
// First parameter is target URL (mandatory).
let url = match env::args().nth(1) {
Some(ref url) => Uri::from_str(url).map_err(|e| error(format!("{}", e)))?,
None => {
println!("Usage: client <url> <ca_store>");
return Ok(());
}
};
// Second parameter is custom Root-CA store (optional, defaults to native cert store).
let mut ca = match env::args().nth(2) {
Some(ref path) => {
let f = fs::File::open(path)
.map_err(|e| error(format!("failed to open {}: {}", path, e)))?;
let rd = io::BufReader::new(f);
Some(rd)
}
None => None,
};
// Prepare the TLS client config
let tls = match ca {
Some(ref mut rd) => {
// Read trust roots
let certs = rustls_pemfile::certs(rd).collect::<Result<Vec<_>, _>>()?;
let mut roots = RootCertStore::empty();
roots.add_parsable_certificates(certs);
// TLS client config using the custom CA store for lookups
rustls::ClientConfig::builder()
.with_root_certificates(roots)
.with_no_client_auth()
}
// Default TLS client config with native roots
None => rustls::ClientConfig::builder()
.with_native_roots()?
.with_no_client_auth(),
};
// Prepare the HTTPS connector
let https = hyper_rustls::HttpsConnectorBuilder::new()
.with_tls_config(tls)
.https_or_http()
.enable_http1()
.build();
// Build the hyper client from the HTTPS connector.
let client: Client<_, Empty<Bytes>> = Client::builder(TokioExecutor::new()).build(https);
// Prepare a chain of futures which sends a GET request, inspects
// the returned headers, collects the whole body and prints it to
// stdout.
let fut = async move {
let res = client
.get(url)
.await
.map_err(|e| error(format!("Could not get: {:?}", e)))?;
println!("Status:\n{}", res.status());
println!("Headers:\n{:#?}", res.headers());
let body = res
.into_body()
.collect()
.await
.map_err(|e| error(format!("Could not get body: {:?}", e)))?
.to_bytes();
println!("Body:\n{}", String::from_utf8_lossy(&body));
Ok(())
};
fut.await
}

View File

@@ -0,0 +1,25 @@
[ v3_end ]
basicConstraints = critical,CA:false
keyUsage = nonRepudiation, digitalSignature
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
subjectAltName = @alt_names
[ v3_client ]
basicConstraints = critical,CA:false
keyUsage = nonRepudiation, digitalSignature
extendedKeyUsage = critical, clientAuth
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[ v3_inter ]
subjectKeyIdentifier = hash
extendedKeyUsage = critical, serverAuth, clientAuth
basicConstraints = CA:true
keyUsage = cRLSign, keyCertSign, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign
[ alt_names ]
DNS.1 = testserver.com
DNS.2 = second.testserver.com
DNS.3 = localhost

View File

@@ -0,0 +1,56 @@
#!/bin/sh
set -xe
openssl req -nodes \
-x509 \
-days 3650 \
-newkey rsa:4096 \
-keyout ca.key \
-out ca.cert \
-sha256 \
-batch \
-subj "/CN=ponytown RSA CA"
openssl req -nodes \
-newkey rsa:3072 \
-keyout inter.key \
-out inter.req \
-sha256 \
-batch \
-subj "/CN=ponytown RSA level 2 intermediate"
openssl req -nodes \
-newkey rsa:2048 \
-keyout end.key \
-out end.req \
-sha256 \
-batch \
-subj "/CN=testserver.com"
openssl rsa \
-in end.key \
-out sample.rsa
openssl x509 -req \
-in inter.req \
-out inter.cert \
-CA ca.cert \
-CAkey ca.key \
-sha256 \
-days 3650 \
-set_serial 123 \
-extensions v3_inter -extfile openssl.cnf
openssl x509 -req \
-in end.req \
-out end.cert \
-CA inter.cert \
-CAkey inter.key \
-sha256 \
-days 2000 \
-set_serial 456 \
-extensions v3_end -extfile openssl.cnf
cat end.cert inter.cert ca.cert > sample.pem
rm *.key *.cert *.req

79
vendor/hyper-rustls/examples/sample.pem vendored Normal file
View File

@@ -0,0 +1,79 @@
-----BEGIN CERTIFICATE-----
MIIEADCCAmigAwIBAgICAcgwDQYJKoZIhvcNAQELBQAwLDEqMCgGA1UEAwwhcG9u
eXRvd24gUlNBIGxldmVsIDIgaW50ZXJtZWRpYXRlMB4XDTIyMDcwNDE0MzA1OFoX
DTI3MTIyNTE0MzA1OFowGTEXMBUGA1UEAwwOdGVzdHNlcnZlci5jb20wggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDL35qLQLIqswCmHJxyczYF2p0YxXCq
gMvtRcKVElnifPMFrbGCY1aYBmhIiXPGRwhfythAtYfDQsrXFADZd52JPgZCR/u6
DQMqKD2lcvFQkf7Kee/fNTOuQTQPh1XQx4ntxvicSATwEnuU28NwVnOU//Zzq2xn
Q34gUQNHWp1pN+B1La7emm/Ucgs1/2hMxwCZYUnRoiUoRGXUSzZuWokDOstPNkjc
+AjHmxONgowogmL2jKN9BjBw/8psGoqEOjMO+Lb9iekOCzX4kqHaRUbTlbSAviQu
2Q115xiZCBCZVtNE6DUG25buvpMSEXwpLd96nLywbrSCyueC7cd01/hpAgMBAAGj
gb4wgbswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwHQYDVR0OBBYEFHGnzC5Q
A62Wmv4zfMk/kf/BxHevMEIGA1UdIwQ7MDmAFDMRUvwxXbYDBCxOdQ9xfBnNWUz0
oR6kHDAaMRgwFgYDVQQDDA9wb255dG93biBSU0EgQ0GCAXswOwYDVR0RBDQwMoIO
dGVzdHNlcnZlci5jb22CFXNlY29uZC50ZXN0c2VydmVyLmNvbYIJbG9jYWxob3N0
MA0GCSqGSIb3DQEBCwUAA4IBgQBqKNIM/JBGRmGEopm5/WNKV8UoxKPA+2jR020t
RumXMAnJEfhsivF+Zw/rDmSDpmts/3cIlesKi47f13q4Mfj1QytQUDrsuQEyRTrV
Go6BOQQ4dkS+IqnIfSuue70wpvrZHhRHNFdFt9qM5wCLQokXlP988sEWUmyPPCbO
1BEpwWcP1kx+PdY8NKOhMnfq2RfluI/m4MA4NxJqAWajAhIbDNbvP8Ov4a71HPa6
b1q9qIQE1ut8KycTrm9K32bVbvMHvR/TPUue8W0VvV2rWTGol5TSNgEQb9w6Kyf7
N5HlRl9kZB4K8ckWH/JVn0pYNBQPgwbcUbJ/jp6w+LHrh+UW75maOY+IGjVICud8
6Rc5DZZ2+AAbXJQZ1HMPrw9SW/16Eh/A4CIEsvbu9J+7IoSzhgcKFzOCUojzzRSj
iU7w/HsvpltmVCAZcZ/VARFbe1By2wXX2GSw2p2FVC8orXs76QyruPAVgSHCTVes
zzBo6GLScO/3b6uAcPM3MHRGGvE=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEnzCCAoegAwIBAgIBezANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9wb255
dG93biBSU0EgQ0EwHhcNMjIwNzA0MTQzMDU4WhcNMzIwNzAxMTQzMDU4WjAsMSow
KAYDVQQDDCFwb255dG93biBSU0EgbGV2ZWwgMiBpbnRlcm1lZGlhdGUwggGiMA0G
CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCsTkd2SKiy3yy20lygOhKfOySo3qpq
TZVrpW11vQ58+6EcetXRnzIIK0HyhPmZrv9XKPpQclJvfY9jADNtu2CSj/v15OSB
Love3GzmXSZz2A8QUZBPWx6HczDG1hFGzrCZPKzpeLnFD1LPsKCUkUOHl1acyy24
DaCacQJPzPQWbMhbGmYRlDNb+2R2K6UKMAEVe4IOTv2aSIKDGLI+xlaBXYAJj48L
//9eNmR3bMP3kkNKOKaaBk8vnYxKpZ+8ZHeHTmYWR9x1ZoMcbA9lKUwRpKAjY5JJ
NVZMDmjlVQVvvBrvhgz/zgXtfuaQCryZ0f1sEY/zXhdealo3fGVomeoniD4XwA1c
oaUFkbo5IM5HU/pXyAGRerDyhYLgRqQZMIRauvKRPN3jLsPOEQ0+gnXUUTr/YGIE
KY3/Axg4P3hzZCFqJ5IgkgWZr/dKr9p/0cxSUGHTVcpEFOlkKIIIdRuR7Ng5sJml
u7PAMWt6T+x02ORs1/WkyP7LyPQmuugYTicCAwEAAaNeMFwwHQYDVR0OBBYEFDMR
UvwxXbYDBCxOdQ9xfBnNWUz0MCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEF
BQcDAjAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIB/jANBgkqhkiG9w0BAQsFAAOC
AgEAYzqmX+cNPgVD2HWgbeimUraTpI9JP5P4TbOHWmaJKecoy3Hwr71xyAOGiVXL
urk1ZZe8n++GwuDEgRajN3HO9LR1Pu9qVIzTYIsz0ORRQHxujnF7CxK/I/vrIgde
pddUdHNS0Y0g8J1emH9BgoD8a2YsGX4iDY4S4hIGBbGvQp9z8U/uG1mViAmlXybM
b8bf0dx0tEFUyu8jsQP6nFLY/HhkEcvU6SnOzZHRsFko6NE44VIsHLd2+LS2LCM/
NfAoTzgvj41M3zQCZapaHZc9KXfdcCvEFaySKGfEZeQTUR5W0FHsF5I4NLGryf5L
h3ENQ1tgBTO5WnqL/5rbgv6va9VionPM5sbEwAcancejnkVs3NoYPIPPgBFjaFmL
hNTpT9H2owdZvEwNDChVS0b8ukNNd4cERtvy0Ohc3mk0LGN0ABzrud0fIqa51LMh
0N3dkPkiZ4XYk4yLJ5EwCrCNNH50QkGCOWpInKIPeSYcALGgBDbCDLv6rV3oSKrV
tHCZQwXVKKgU4AQu7hlHBwJ61cH44ksydOidW3MNq1kDIp7ST8s7gVrItNgFnG+L
Jpo270riwSUlWDY4hXw5Ff5lE+bWCmFyyOkLevDkD9v8M4HdwEVvafYYwn75fCIS
5OnpSeIB08kKqCtW1WBwki0rYJjWqdzI7Z1MQ/AyScAKiGM=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEsDCCApgCCQCfkxy3a+AgNjANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9w
b255dG93biBSU0EgQ0EwHhcNMjIwNzA0MTQzMDU3WhcNMzIwNzAxMTQzMDU3WjAa
MRgwFgYDVQQDDA9wb255dG93biBSU0EgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC
DwAwggIKAoICAQCj6nW8pnN50UsH2NjL97xZKxlXPe5ptXfvqXczMsw0vB3gI4xJ
Tdmrnqo0K+VOH7vh+UXcOj2ZMY2ou6oDDK5Qpu9bvGPBIJH/rC1Ti2+u5Y4KTIUc
jWAtzQJeFn8+oCMfskpLdtlWLRdAuwqNHjvxXdd2JnsX1Wid85U/rG2SNPLGjJAF
xG7xzZC4VSO2WIXTGRMUkZfFc8fhWMjo3GaeF/qYjzfHDPWN/ll/7vfxyXJO/ohw
FzpJSZtKmI+6PLxqB/oFrKfTDQUGzxjfHp187bI3eyUFMJsp18/tLYkLyxSWIg3o
bq7ZVimHd1UG2Vb5Y+5pZkh22jmJ6bAa/kmNNwbsD+5vJhW1myGhmZSxkreYPWnS
6ELrSMvbXccFfTYmdBlWsZx/zUVUzVCPe9jdJki2VXlicohqtvBQqe6LGGO37vvv
Gwu1yzQ/rJy47rnaao7fSxqM8nsDjNR2Ev1v031QpEMWjfgUW0roW3H58RZSx+kU
gzIS2CjJIqKxCp894FUQbC6r0wwAuKltl3ywz5qWkxY0O9bXS0YdEXiri5pdsWjr
84shVVQwnoVD9539CLSdHZjlOCAzvSWHZH6ta2JZjUfYYz8cLyv2c2+y9BYrlvHw
T7U7BqzngUk72gcRXd5+Onp+16gGxpGJqaxqj94Nh/yTUnr2Jd9YaXeFmQIDAQAB
MA0GCSqGSIb3DQEBCwUAA4ICAQBzIRVRt3Yaw60tpkyz/i1xbKCbtC+HqYTEsXvZ
RvZ5X1qyLAcmu4EW9RHXnlLiawDbES6lCMFfdBUK03Wis7socvoFUCBRW337F4z2
IivHfIge4u+w5ouUKPzcpj6oeuR06tmNytYbno6l8tXJpm1eeO4KNZ0ZtodmyB5D
yLrplFgxTdGGgyvxt8LoeLwGmPCyVt35x/Mz6x2lcq1+r7QJZ9sENhQYuA8UqHrw
fmNoVIMXMEcPLcWtFl6nKTK9LrqAu1jgTBqGGZKRn5CYBBK3pNEGKiOIsZXDbyFS
F59teFpJjyeJTbUbLxXDa15J6ExkHV9wFLEvfu/nzQzg8D9yzczSdbDkE2rrrL+s
Q/H/pIXO/DesCWQ37VALn3B5gm9UBd5uogbSw8eamiwRFLQ0snP80pJQGJoTNn0P
wrLLUf2gsKC2262igiA+imepm5wxbV9XGVZfHJgxCi5Zqrf6aWnjIqD2YtDvAHhs
V8ZWN3QTjdnEcQbG0544rocoLNX/FzmyDgjfZKY5r6wt+FWNc/R4clkF+KxasxqB
HdBs8j0lGV3ujvNXASLq9HI6VxZayrSfkR73hADCXIM/wzynKwMarvA4SXwYX9Pd
cJ4+FMqrevPpamMHUsNndS0KfDTdjDp+TSBf87yiyRkD1Ri4ePslyfNvRyv3Xs7k
47YFzA==
-----END CERTIFICATE-----

27
vendor/hyper-rustls/examples/sample.rsa vendored Normal file
View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAy9+ai0CyKrMAphyccnM2BdqdGMVwqoDL7UXClRJZ4nzzBa2x
gmNWmAZoSIlzxkcIX8rYQLWHw0LK1xQA2XediT4GQkf7ug0DKig9pXLxUJH+ynnv
3zUzrkE0D4dV0MeJ7cb4nEgE8BJ7lNvDcFZzlP/2c6tsZ0N+IFEDR1qdaTfgdS2u
3ppv1HILNf9oTMcAmWFJ0aIlKERl1Es2blqJAzrLTzZI3PgIx5sTjYKMKIJi9oyj
fQYwcP/KbBqKhDozDvi2/YnpDgs1+JKh2kVG05W0gL4kLtkNdecYmQgQmVbTROg1
BtuW7r6TEhF8KS3fepy8sG60gsrngu3HdNf4aQIDAQABAoIBAFTehqVFj2W7EqAT
9QSn9WtGcHNpbddsunfRvIj2FLj2LuzEO8r9s4Sh1jOsFKgL1e6asJ9vck7UtUAH
sbrV0pzZVx2sfZwb4p9gFRmU2eQigqCjVjnjGdqGhjeYrR62kjKLy96zFGskJpH3
UkqnkoIKc/v+9qeeLxkg4G6JyFGOFHJAZEraxoGydJk9n/yBEZ/+3W7JUJaGOUNU
M7BYsCS2VOJr+cCqmCk1j8NvYvWWxTPsIXgGJl4EOoskzlzJnYLdh9fPFZu3uOIx
hpm3DBNp6X+qXf1lmx9EdpyeXKpLFIgJM7+nw2uWzxW7XMlRERi+5Tprc/pjrqUq
gpfyvMkCgYEA909QcJpS3qHoWyxGbI1zosVIZXdnj8L+GF/2kEQEU5iEYT+2M1U+
gCPLr49gNwkD1FdBSCy+Fw20zi35jGmxNwhgp4V94CGYzqwQzpnvgIRBMiAIoEwI
CD5/t34DZ/82u8Gb7UYVrzOD54rJ628Q+tJEJak3TqoShbvcxJC/rXMCgYEA0wmO
SRoxrBE3rFzNQkqHbMHLe9LksW9YSIXdMBjq4DhzQEwI0YgPLajXnsLurqHaJrQA
JPtYkqiJkV7rvJLBo5wxwU+O2JKKa2jcMwuCZ4hOg5oBfK6ES9QJZUL7kDe2vsWy
rL+rnxJheUjDPBTopGHuuc9Nogid35CE0wy7S7MCgYArxB+KLeVofOKv79/uqgHC
1oL/Yegz6uAo1CLAWSki2iTjSPEnmHhdGPic8xSl6LSCyYZGDZT+Y3CR5FT7YmD4
SkVAoEEsfwWZ3Z2D0n4uEjmvczfTlmD9hIH5qRVVPDcldxfvH64KuWUofslJHvi0
Sq3AtHeTNknc3Ogu6SbivQKBgQC4ZAsMWHS6MTkBwvwdRd1Z62INyNDFL9JlW4FN
uxfN3cTlkwnJeiY48OOk9hFySDzBwFi3910Gl3fLqrIyy8+hUqIuk4LuO+vxuWdc
uluwdmqTlgZimGFDl/q1nXcMJYHo4fgh9D7R+E9ul2Luph43MtJRS447W2gFpNJJ
TUCA/QKBgQC07GFP2BN74UvL12f+FpZvE/UFtWnSZ8yJSq8oYpIbhmoF5EUF+XdA
E2y3l1cvmDJFo4RNZl+IQIbHACR3y1XOnh4/B9fMEsVQHK3x8exPk1vAk687bBG8
TVDmdP52XEKHplcVoYKvGzw/wsObLAGyIbJ00t1VPU+7guTPsc+H/w==
-----END RSA PRIVATE KEY-----

138
vendor/hyper-rustls/examples/server.rs vendored Normal file
View File

@@ -0,0 +1,138 @@
//! Simple HTTPS echo service based on hyper_util and rustls
//!
//! First parameter is the mandatory port to use.
//! Certificate and private key are hardcoded to sample files.
//! hyper will automatically use HTTP/2 if a client starts talking HTTP/2,
//! otherwise HTTP/1.1 will be used.
use std::net::{Ipv4Addr, SocketAddr};
use std::sync::Arc;
use std::{env, fs, io};
use http::{Method, Request, Response, StatusCode};
use http_body_util::{BodyExt, Full};
use hyper::body::{Bytes, Incoming};
use hyper::service::service_fn;
use hyper_util::rt::{TokioExecutor, TokioIo};
use hyper_util::server::conn::auto::Builder;
use pki_types::{CertificateDer, PrivateKeyDer};
use rustls::ServerConfig;
use tokio::net::TcpListener;
use tokio_rustls::TlsAcceptor;
fn main() {
// Serve an echo service over HTTPS, with proper error handling.
if let Err(e) = run_server() {
eprintln!("FAILED: {}", e);
std::process::exit(1);
}
}
fn error(err: String) -> io::Error {
io::Error::new(io::ErrorKind::Other, err)
}
#[tokio::main]
async fn run_server() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Set a process wide default crypto provider.
#[cfg(feature = "ring")]
let _ = rustls::crypto::ring::default_provider().install_default();
#[cfg(feature = "aws-lc-rs")]
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
// First parameter is port number (optional, defaults to 1337)
let port = match env::args().nth(1) {
Some(ref p) => p.parse()?,
None => 1337,
};
let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), port);
// Load public certificate.
let certs = load_certs("examples/sample.pem")?;
// Load private key.
let key = load_private_key("examples/sample.rsa")?;
println!("Starting to serve on https://{}", addr);
// Create a TCP listener via tokio.
let incoming = TcpListener::bind(&addr).await?;
// Build TLS configuration.
let mut server_config = ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(certs, key)
.map_err(|e| error(e.to_string()))?;
server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()];
let tls_acceptor = TlsAcceptor::from(Arc::new(server_config));
let service = service_fn(echo);
loop {
let (tcp_stream, _remote_addr) = incoming.accept().await?;
let tls_acceptor = tls_acceptor.clone();
tokio::spawn(async move {
let tls_stream = match tls_acceptor.accept(tcp_stream).await {
Ok(tls_stream) => tls_stream,
Err(err) => {
eprintln!("failed to perform tls handshake: {err:#}");
return;
}
};
if let Err(err) = Builder::new(TokioExecutor::new())
.serve_connection(TokioIo::new(tls_stream), service)
.await
{
eprintln!("failed to serve connection: {err:#}");
}
});
}
}
// Custom echo service, handling two different routes and a
// catch-all 404 responder.
async fn echo(req: Request<Incoming>) -> Result<Response<Full<Bytes>>, hyper::Error> {
let mut response = Response::new(Full::default());
match (req.method(), req.uri().path()) {
// Help route.
(&Method::GET, "/") => {
*response.body_mut() = Full::from("Try POST /echo\n");
}
// Echo service route.
(&Method::POST, "/echo") => {
*response.body_mut() = Full::from(
req.into_body()
.collect()
.await?
.to_bytes(),
);
}
// Catch-all 404.
_ => {
*response.status_mut() = StatusCode::NOT_FOUND;
}
};
Ok(response)
}
// Load public certificate from file.
fn load_certs(filename: &str) -> io::Result<Vec<CertificateDer<'static>>> {
// Open certificate file.
let certfile = fs::File::open(filename)
.map_err(|e| error(format!("failed to open {}: {}", filename, e)))?;
let mut reader = io::BufReader::new(certfile);
// Load and return certificate.
rustls_pemfile::certs(&mut reader).collect()
}
// Load private key from file.
fn load_private_key(filename: &str) -> io::Result<PrivateKeyDer<'static>> {
// Open keyfile.
let keyfile = fs::File::open(filename)
.map_err(|e| error(format!("failed to open {}: {}", filename, e)))?;
let mut reader = io::BufReader::new(keyfile);
// Load and return a single private key.
rustls_pemfile::private_key(&mut reader).map(|key| key.unwrap())
}

136
vendor/hyper-rustls/src/config.rs vendored Normal file
View File

@@ -0,0 +1,136 @@
#[cfg(feature = "rustls-native-certs")]
use std::io;
#[cfg(any(
feature = "rustls-platform-verifier",
feature = "rustls-native-certs",
feature = "webpki-roots"
))]
use rustls::client::WantsClientCert;
use rustls::{ClientConfig, ConfigBuilder, WantsVerifier};
#[cfg(feature = "rustls-native-certs")]
use rustls_native_certs::CertificateResult;
#[cfg(feature = "rustls-platform-verifier")]
use rustls_platform_verifier::BuilderVerifierExt;
/// Methods for configuring roots
///
/// This adds methods (gated by crate features) for easily configuring
/// TLS server roots a rustls ClientConfig will trust.
pub trait ConfigBuilderExt: sealed::Sealed {
/// Use the platform's native verifier to verify server certificates.
///
/// See the documentation for [rustls-platform-verifier] for more details.
///
/// # Panics
///
/// Since 0.27.7, this method will panic if the platform verifier cannot be initialized.
/// Use `try_with_platform_verifier()` instead to handle errors gracefully.
///
/// [rustls-platform-verifier]: https://docs.rs/rustls-platform-verifier
#[deprecated(since = "0.27.7", note = "use `try_with_platform_verifier` instead")]
#[cfg(feature = "rustls-platform-verifier")]
fn with_platform_verifier(self) -> ConfigBuilder<ClientConfig, WantsClientCert>;
/// Use the platform's native verifier to verify server certificates.
///
/// See the documentation for [rustls-platform-verifier] for more details.
///
/// [rustls-platform-verifier]: https://docs.rs/rustls-platform-verifier
#[cfg(feature = "rustls-platform-verifier")]
fn try_with_platform_verifier(
self,
) -> Result<ConfigBuilder<ClientConfig, WantsClientCert>, rustls::Error>;
/// This configures the platform's trusted certs, as implemented by
/// rustls-native-certs
///
/// This will return an error if no valid certs were found. In that case,
/// it's recommended to use `with_webpki_roots`.
#[cfg(feature = "rustls-native-certs")]
fn with_native_roots(self) -> Result<ConfigBuilder<ClientConfig, WantsClientCert>, io::Error>;
/// This configures the webpki roots, which are Mozilla's set of
/// trusted roots as packaged by webpki-roots.
#[cfg(feature = "webpki-roots")]
fn with_webpki_roots(self) -> ConfigBuilder<ClientConfig, WantsClientCert>;
}
impl ConfigBuilderExt for ConfigBuilder<ClientConfig, WantsVerifier> {
#[cfg(feature = "rustls-platform-verifier")]
fn with_platform_verifier(self) -> ConfigBuilder<ClientConfig, WantsClientCert> {
self.try_with_platform_verifier()
.expect("failure to initialize platform verifier")
}
#[cfg(feature = "rustls-platform-verifier")]
fn try_with_platform_verifier(
self,
) -> Result<ConfigBuilder<ClientConfig, WantsClientCert>, rustls::Error> {
BuilderVerifierExt::with_platform_verifier(self)
}
#[cfg(feature = "rustls-native-certs")]
#[cfg_attr(not(feature = "logging"), allow(unused_variables))]
fn with_native_roots(self) -> Result<ConfigBuilder<ClientConfig, WantsClientCert>, io::Error> {
let mut roots = rustls::RootCertStore::empty();
let mut valid_count = 0;
let mut invalid_count = 0;
let CertificateResult { certs, errors, .. } = rustls_native_certs::load_native_certs();
if !errors.is_empty() {
crate::log::warn!("native root CA certificate loading errors: {errors:?}");
}
if certs.is_empty() {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("no native root CA certificates found (errors: {errors:?})"),
));
}
for cert in certs {
match roots.add(cert) {
Ok(_) => valid_count += 1,
Err(err) => {
crate::log::debug!("certificate parsing failed: {:?}", err);
invalid_count += 1
}
}
}
crate::log::debug!(
"with_native_roots processed {} valid and {} invalid certs",
valid_count,
invalid_count
);
if roots.is_empty() {
crate::log::debug!("no valid native root CA certificates found");
Err(io::Error::new(
io::ErrorKind::NotFound,
format!("no valid native root CA certificates found ({invalid_count} invalid)"),
))?
}
Ok(self.with_root_certificates(roots))
}
#[cfg(feature = "webpki-roots")]
fn with_webpki_roots(self) -> ConfigBuilder<ClientConfig, WantsClientCert> {
let mut roots = rustls::RootCertStore::empty();
roots.extend(
webpki_roots::TLS_SERVER_ROOTS
.iter()
.cloned(),
);
self.with_root_certificates(roots)
}
}
mod sealed {
use super::*;
pub trait Sealed {}
impl Sealed for ConfigBuilder<ClientConfig, WantsVerifier> {}
}

296
vendor/hyper-rustls/src/connector.rs vendored Normal file
View File

@@ -0,0 +1,296 @@
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use std::{fmt, io};
use http::Uri;
use hyper::rt;
use hyper_util::client::legacy::connect::Connection;
use hyper_util::rt::TokioIo;
use pki_types::ServerName;
use tokio_rustls::TlsConnector;
use tower_service::Service;
use crate::stream::MaybeHttpsStream;
pub(crate) mod builder;
type BoxError = Box<dyn std::error::Error + Send + Sync>;
/// A Connector for the `https` scheme.
#[derive(Clone)]
pub struct HttpsConnector<T> {
force_https: bool,
http: T,
tls_config: Arc<rustls::ClientConfig>,
server_name_resolver: Arc<dyn ResolveServerName + Sync + Send>,
}
impl<T> HttpsConnector<T> {
/// Creates a [`crate::HttpsConnectorBuilder`] to configure a `HttpsConnector`.
///
/// This is the same as [`crate::HttpsConnectorBuilder::new()`].
pub fn builder() -> builder::ConnectorBuilder<builder::WantsTlsConfig> {
builder::ConnectorBuilder::new()
}
/// Force the use of HTTPS when connecting.
///
/// If a URL is not `https` when connecting, an error is returned.
pub fn enforce_https(&mut self) {
self.force_https = true;
}
}
impl<T> Service<Uri> for HttpsConnector<T>
where
T: Service<Uri>,
T::Response: Connection + rt::Read + rt::Write + Send + Unpin + 'static,
T::Future: Send + 'static,
T::Error: Into<BoxError>,
{
type Response = MaybeHttpsStream<T::Response>;
type Error = BoxError;
#[allow(clippy::type_complexity)]
type Future =
Pin<Box<dyn Future<Output = Result<MaybeHttpsStream<T::Response>, BoxError>> + Send>>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
match self.http.poll_ready(cx) {
Poll::Ready(Ok(())) => Poll::Ready(Ok(())),
Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())),
Poll::Pending => Poll::Pending,
}
}
fn call(&mut self, dst: Uri) -> Self::Future {
// dst.scheme() would need to derive Eq to be matchable;
// use an if cascade instead
match dst.scheme() {
Some(scheme) if scheme == &http::uri::Scheme::HTTP && !self.force_https => {
let future = self.http.call(dst);
return Box::pin(async move {
Ok(MaybeHttpsStream::Http(future.await.map_err(Into::into)?))
});
}
Some(scheme) if scheme != &http::uri::Scheme::HTTPS => {
let message = format!("unsupported scheme {scheme}");
return Box::pin(async move {
Err(io::Error::new(io::ErrorKind::Other, message).into())
});
}
Some(_) => {}
None => {
return Box::pin(async move {
Err(io::Error::new(io::ErrorKind::Other, "missing scheme").into())
})
}
};
let cfg = self.tls_config.clone();
let hostname = match self.server_name_resolver.resolve(&dst) {
Ok(hostname) => hostname,
Err(e) => {
return Box::pin(async move { Err(e) });
}
};
let connecting_future = self.http.call(dst);
Box::pin(async move {
let tcp = connecting_future
.await
.map_err(Into::into)?;
Ok(MaybeHttpsStream::Https(TokioIo::new(
TlsConnector::from(cfg)
.connect(hostname, TokioIo::new(tcp))
.await
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
)))
})
}
}
impl<H, C> From<(H, C)> for HttpsConnector<H>
where
C: Into<Arc<rustls::ClientConfig>>,
{
fn from((http, cfg): (H, C)) -> Self {
Self {
force_https: false,
http,
tls_config: cfg.into(),
server_name_resolver: Arc::new(DefaultServerNameResolver::default()),
}
}
}
impl<T> fmt::Debug for HttpsConnector<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("HttpsConnector")
.field("force_https", &self.force_https)
.finish()
}
}
/// The default server name resolver, which uses the hostname in the URI.
#[derive(Default)]
pub struct DefaultServerNameResolver(());
impl ResolveServerName for DefaultServerNameResolver {
fn resolve(
&self,
uri: &Uri,
) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>> {
let mut hostname = uri.host().unwrap_or_default();
// Remove square brackets around IPv6 address.
if let Some(trimmed) = hostname
.strip_prefix('[')
.and_then(|h| h.strip_suffix(']'))
{
hostname = trimmed;
}
ServerName::try_from(hostname.to_string()).map_err(|e| Box::new(e) as _)
}
}
/// A server name resolver which always returns the same fixed name.
pub struct FixedServerNameResolver {
name: ServerName<'static>,
}
impl FixedServerNameResolver {
/// Creates a new resolver returning the specified name.
pub fn new(name: ServerName<'static>) -> Self {
Self { name }
}
}
impl ResolveServerName for FixedServerNameResolver {
fn resolve(
&self,
_: &Uri,
) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>> {
Ok(self.name.clone())
}
}
impl<F, E> ResolveServerName for F
where
F: Fn(&Uri) -> Result<ServerName<'static>, E>,
E: Into<Box<dyn std::error::Error + Sync + Send>>,
{
fn resolve(
&self,
uri: &Uri,
) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>> {
self(uri).map_err(Into::into)
}
}
/// A trait implemented by types that can resolve a [`ServerName`] for a request.
pub trait ResolveServerName {
/// Maps a [`Uri`] into a [`ServerName`].
fn resolve(
&self,
uri: &Uri,
) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>>;
}
#[cfg(all(
test,
any(feature = "ring", feature = "aws-lc-rs"),
any(
feature = "rustls-native-certs",
feature = "webpki-roots",
feature = "rustls-platform-verifier",
)
))]
mod tests {
use std::future::poll_fn;
use http::Uri;
use hyper_util::rt::TokioIo;
use tokio::net::TcpStream;
use tower_service::Service;
use super::*;
use crate::{ConfigBuilderExt, HttpsConnectorBuilder, MaybeHttpsStream};
#[tokio::test]
async fn connects_https() {
connect(Allow::Any, Scheme::Https)
.await
.unwrap();
}
#[tokio::test]
async fn connects_http() {
connect(Allow::Any, Scheme::Http)
.await
.unwrap();
}
#[tokio::test]
async fn connects_https_only() {
connect(Allow::Https, Scheme::Https)
.await
.unwrap();
}
#[tokio::test]
async fn enforces_https_only() {
let message = connect(Allow::Https, Scheme::Http)
.await
.unwrap_err()
.to_string();
assert_eq!(message, "unsupported scheme http");
}
async fn connect(
allow: Allow,
scheme: Scheme,
) -> Result<MaybeHttpsStream<TokioIo<TcpStream>>, BoxError> {
let config_builder = rustls::ClientConfig::builder();
cfg_if::cfg_if! {
if #[cfg(feature = "rustls-platform-verifier")] {
let config_builder = config_builder.try_with_platform_verifier()?;
} else if #[cfg(feature = "rustls-native-certs")] {
let config_builder = config_builder.with_native_roots().unwrap();
} else if #[cfg(feature = "webpki-roots")] {
let config_builder = config_builder.with_webpki_roots();
}
}
let config = config_builder.with_no_client_auth();
let builder = HttpsConnectorBuilder::new().with_tls_config(config);
let mut service = match allow {
Allow::Https => builder.https_only(),
Allow::Any => builder.https_or_http(),
}
.enable_http1()
.build();
poll_fn(|cx| service.poll_ready(cx)).await?;
service
.call(Uri::from_static(match scheme {
Scheme::Https => "https://google.com",
Scheme::Http => "http://google.com",
}))
.await
}
enum Allow {
Https,
Any,
}
enum Scheme {
Https,
Http,
}
}

View File

@@ -0,0 +1,500 @@
use std::sync::Arc;
use hyper_util::client::legacy::connect::HttpConnector;
#[cfg(any(
feature = "rustls-native-certs",
feature = "rustls-platform-verifier",
feature = "webpki-roots"
))]
use rustls::crypto::CryptoProvider;
use rustls::ClientConfig;
use super::{DefaultServerNameResolver, HttpsConnector, ResolveServerName};
#[cfg(any(
feature = "rustls-native-certs",
feature = "webpki-roots",
feature = "rustls-platform-verifier"
))]
use crate::config::ConfigBuilderExt;
use pki_types::ServerName;
/// A builder for an [`HttpsConnector`]
///
/// This makes configuration flexible and explicit and ensures connector
/// features match crate features
///
/// # Examples
///
/// ```
/// use hyper_rustls::HttpsConnectorBuilder;
///
/// # #[cfg(all(feature = "webpki-roots", feature = "http1", feature="aws-lc-rs"))]
/// # {
/// # let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
/// let https = HttpsConnectorBuilder::new()
/// .with_webpki_roots()
/// .https_only()
/// .enable_http1()
/// .build();
/// # }
/// ```
pub struct ConnectorBuilder<State>(State);
/// State of a builder that needs a TLS client config next
pub struct WantsTlsConfig(());
impl ConnectorBuilder<WantsTlsConfig> {
/// Creates a new [`ConnectorBuilder`]
pub fn new() -> Self {
Self(WantsTlsConfig(()))
}
/// Passes a rustls [`ClientConfig`] to configure the TLS connection
///
/// The [`alpn_protocols`](ClientConfig::alpn_protocols) field is
/// required to be empty (or the function will panic) and will be
/// rewritten to match the enabled schemes (see
/// [`enable_http1`](ConnectorBuilder::enable_http1),
/// [`enable_http2`](ConnectorBuilder::enable_http2)) before the
/// connector is built.
pub fn with_tls_config(self, config: ClientConfig) -> ConnectorBuilder<WantsSchemes> {
assert!(
config.alpn_protocols.is_empty(),
"ALPN protocols should not be pre-defined"
);
ConnectorBuilder(WantsSchemes { tls_config: config })
}
/// Shorthand for using rustls' default crypto provider and other defaults, and
/// the platform verifier.
///
/// See [`ConfigBuilderExt::with_platform_verifier()`].
#[cfg(all(
any(feature = "ring", feature = "aws-lc-rs"),
feature = "rustls-platform-verifier"
))]
pub fn with_platform_verifier(self) -> ConnectorBuilder<WantsSchemes> {
self.try_with_platform_verifier()
.expect("failure to initialize platform verifier")
}
/// Shorthand for using rustls' default crypto provider and other defaults, and
/// the platform verifier.
///
/// See [`ConfigBuilderExt::with_platform_verifier()`].
#[cfg(all(
any(feature = "ring", feature = "aws-lc-rs"),
feature = "rustls-platform-verifier"
))]
pub fn try_with_platform_verifier(
self,
) -> Result<ConnectorBuilder<WantsSchemes>, rustls::Error> {
Ok(self.with_tls_config(
ClientConfig::builder()
.try_with_platform_verifier()?
.with_no_client_auth(),
))
}
/// Shorthand for using a custom [`CryptoProvider`] and the platform verifier.
///
/// See [`ConfigBuilderExt::with_platform_verifier()`].
#[cfg(feature = "rustls-platform-verifier")]
pub fn with_provider_and_platform_verifier(
self,
provider: impl Into<Arc<CryptoProvider>>,
) -> std::io::Result<ConnectorBuilder<WantsSchemes>> {
Ok(self.with_tls_config(
ClientConfig::builder_with_provider(provider.into())
.with_safe_default_protocol_versions()
.and_then(|builder| builder.try_with_platform_verifier())
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?
.with_no_client_auth(),
))
}
/// Shorthand for using rustls' default crypto provider and safe defaults, with
/// native roots.
///
/// See [`ConfigBuilderExt::with_native_roots`]
#[cfg(all(
any(feature = "ring", feature = "aws-lc-rs"),
feature = "rustls-native-certs"
))]
pub fn with_native_roots(self) -> std::io::Result<ConnectorBuilder<WantsSchemes>> {
Ok(self.with_tls_config(
ClientConfig::builder()
.with_native_roots()?
.with_no_client_auth(),
))
}
/// Shorthand for using a custom [`CryptoProvider`] and native roots
///
/// See [`ConfigBuilderExt::with_native_roots`]
#[cfg(feature = "rustls-native-certs")]
pub fn with_provider_and_native_roots(
self,
provider: impl Into<Arc<CryptoProvider>>,
) -> std::io::Result<ConnectorBuilder<WantsSchemes>> {
Ok(self.with_tls_config(
ClientConfig::builder_with_provider(provider.into())
.with_safe_default_protocol_versions()
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?
.with_native_roots()?
.with_no_client_auth(),
))
}
/// Shorthand for using rustls' default crypto provider and its
/// safe defaults.
///
/// See [`ConfigBuilderExt::with_webpki_roots`]
#[cfg(all(any(feature = "ring", feature = "aws-lc-rs"), feature = "webpki-roots"))]
pub fn with_webpki_roots(self) -> ConnectorBuilder<WantsSchemes> {
self.with_tls_config(
ClientConfig::builder()
.with_webpki_roots()
.with_no_client_auth(),
)
}
/// Shorthand for using a custom [`CryptoProvider`], Rustls' safe default
/// protocol versions and Mozilla roots
///
/// See [`ConfigBuilderExt::with_webpki_roots`]
#[cfg(feature = "webpki-roots")]
pub fn with_provider_and_webpki_roots(
self,
provider: impl Into<Arc<CryptoProvider>>,
) -> Result<ConnectorBuilder<WantsSchemes>, rustls::Error> {
Ok(self.with_tls_config(
ClientConfig::builder_with_provider(provider.into())
.with_safe_default_protocol_versions()?
.with_webpki_roots()
.with_no_client_auth(),
))
}
}
impl Default for ConnectorBuilder<WantsTlsConfig> {
fn default() -> Self {
Self::new()
}
}
/// State of a builder that needs schemes (https:// and http://) to be
/// configured next
pub struct WantsSchemes {
tls_config: ClientConfig,
}
impl ConnectorBuilder<WantsSchemes> {
/// Enforce the use of HTTPS when connecting
///
/// Only URLs using the HTTPS scheme will be connectable.
pub fn https_only(self) -> ConnectorBuilder<WantsProtocols1> {
ConnectorBuilder(WantsProtocols1 {
tls_config: self.0.tls_config,
https_only: true,
server_name_resolver: None,
})
}
/// Allow both HTTPS and HTTP when connecting
///
/// HTTPS URLs will be handled through rustls,
/// HTTP URLs will be handled by the lower-level connector.
pub fn https_or_http(self) -> ConnectorBuilder<WantsProtocols1> {
ConnectorBuilder(WantsProtocols1 {
tls_config: self.0.tls_config,
https_only: false,
server_name_resolver: None,
})
}
}
/// State of a builder that needs to have some protocols (HTTP1 or later)
/// enabled next
///
/// No protocol has been enabled at this point.
pub struct WantsProtocols1 {
tls_config: ClientConfig,
https_only: bool,
server_name_resolver: Option<Arc<dyn ResolveServerName + Sync + Send>>,
}
impl WantsProtocols1 {
fn wrap_connector<H>(self, conn: H) -> HttpsConnector<H> {
HttpsConnector {
force_https: self.https_only,
http: conn,
tls_config: std::sync::Arc::new(self.tls_config),
server_name_resolver: self
.server_name_resolver
.unwrap_or_else(|| Arc::new(DefaultServerNameResolver::default())),
}
}
fn build(self) -> HttpsConnector<HttpConnector> {
let mut http = HttpConnector::new();
// HttpConnector won't enforce scheme, but HttpsConnector will
http.enforce_http(false);
self.wrap_connector(http)
}
}
impl ConnectorBuilder<WantsProtocols1> {
/// Enable HTTP1
///
/// This needs to be called explicitly, no protocol is enabled by default
#[cfg(feature = "http1")]
pub fn enable_http1(self) -> ConnectorBuilder<WantsProtocols2> {
ConnectorBuilder(WantsProtocols2 { inner: self.0 })
}
/// Enable HTTP2
///
/// This needs to be called explicitly, no protocol is enabled by default
#[cfg(feature = "http2")]
pub fn enable_http2(mut self) -> ConnectorBuilder<WantsProtocols3> {
self.0.tls_config.alpn_protocols = vec![b"h2".to_vec()];
ConnectorBuilder(WantsProtocols3 {
inner: self.0,
enable_http1: false,
})
}
/// Enable all HTTP versions built into this library (enabled with Cargo features)
///
/// For now, this could enable both HTTP 1 and 2, depending on active features.
/// In the future, other supported versions will be enabled as well.
#[cfg(feature = "http2")]
pub fn enable_all_versions(mut self) -> ConnectorBuilder<WantsProtocols3> {
#[cfg(feature = "http1")]
let alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
#[cfg(not(feature = "http1"))]
let alpn_protocols = vec![b"h2".to_vec()];
self.0.tls_config.alpn_protocols = alpn_protocols;
ConnectorBuilder(WantsProtocols3 {
inner: self.0,
enable_http1: cfg!(feature = "http1"),
})
}
/// Override server name for the TLS stack
///
/// By default, for each connection hyper-rustls will extract host portion
/// of the destination URL and verify that server certificate contains
/// this value.
///
/// If this method is called, hyper-rustls will instead use this resolver
/// to compute the value used to verify the server certificate.
pub fn with_server_name_resolver(
mut self,
resolver: impl ResolveServerName + 'static + Sync + Send,
) -> Self {
self.0.server_name_resolver = Some(Arc::new(resolver));
self
}
/// Override server name for the TLS stack
///
/// By default, for each connection hyper-rustls will extract host portion
/// of the destination URL and verify that server certificate contains
/// this value.
///
/// If this method is called, hyper-rustls will instead verify that server
/// certificate contains `override_server_name`. Domain name included in
/// the URL will not affect certificate validation.
#[deprecated(
since = "0.27.1",
note = "use Self::with_server_name_resolver with FixedServerNameResolver instead"
)]
pub fn with_server_name(self, mut override_server_name: String) -> Self {
// remove square brackets around IPv6 address.
if let Some(trimmed) = override_server_name
.strip_prefix('[')
.and_then(|s| s.strip_suffix(']'))
{
override_server_name = trimmed.to_string();
}
self.with_server_name_resolver(move |_: &_| {
ServerName::try_from(override_server_name.clone())
})
}
}
/// State of a builder with HTTP1 enabled, that may have some other
/// protocols (HTTP2 or later) enabled next
///
/// At this point a connector can be built, see
/// [`build`](ConnectorBuilder<WantsProtocols2>::build) and
/// [`wrap_connector`](ConnectorBuilder<WantsProtocols2>::wrap_connector).
pub struct WantsProtocols2 {
inner: WantsProtocols1,
}
impl ConnectorBuilder<WantsProtocols2> {
/// Enable HTTP2
///
/// This needs to be called explicitly, no protocol is enabled by default
#[cfg(feature = "http2")]
pub fn enable_http2(mut self) -> ConnectorBuilder<WantsProtocols3> {
self.0.inner.tls_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
ConnectorBuilder(WantsProtocols3 {
inner: self.0.inner,
enable_http1: true,
})
}
/// This builds an [`HttpsConnector`] built on hyper's default [`HttpConnector`]
pub fn build(self) -> HttpsConnector<HttpConnector> {
self.0.inner.build()
}
/// This wraps an arbitrary low-level connector into an [`HttpsConnector`]
pub fn wrap_connector<H>(self, conn: H) -> HttpsConnector<H> {
// HTTP1-only, alpn_protocols stays empty
// HttpConnector doesn't have a way to say http1-only;
// its connection pool may still support HTTP2
// though it won't be used
self.0.inner.wrap_connector(conn)
}
}
/// State of a builder with HTTP2 (and possibly HTTP1) enabled
///
/// At this point a connector can be built, see
/// [`build`](ConnectorBuilder<WantsProtocols3>::build) and
/// [`wrap_connector`](ConnectorBuilder<WantsProtocols3>::wrap_connector).
#[cfg(feature = "http2")]
pub struct WantsProtocols3 {
inner: WantsProtocols1,
// ALPN is built piecemeal without the need to read back this field
#[allow(dead_code)]
enable_http1: bool,
}
#[cfg(feature = "http2")]
impl ConnectorBuilder<WantsProtocols3> {
/// This builds an [`HttpsConnector`] built on hyper's default [`HttpConnector`]
pub fn build(self) -> HttpsConnector<HttpConnector> {
self.0.inner.build()
}
/// This wraps an arbitrary low-level connector into an [`HttpsConnector`]
pub fn wrap_connector<H>(self, conn: H) -> HttpsConnector<H> {
// If HTTP1 is disabled, we can set http2_only
// on the Client (a higher-level object that uses the connector)
// client.http2_only(!self.0.enable_http1);
self.0.inner.wrap_connector(conn)
}
}
#[cfg(test)]
mod tests {
// Typical usage
#[test]
#[cfg(all(feature = "webpki-roots", feature = "http1"))]
fn test_builder() {
ensure_global_state();
let _connector = super::ConnectorBuilder::new()
.with_webpki_roots()
.https_only()
.enable_http1()
.build();
}
#[test]
#[cfg(feature = "http1")]
#[should_panic(expected = "ALPN protocols should not be pre-defined")]
fn test_reject_predefined_alpn() {
ensure_global_state();
let roots = rustls::RootCertStore::empty();
let mut config_with_alpn = rustls::ClientConfig::builder()
.with_root_certificates(roots)
.with_no_client_auth();
config_with_alpn.alpn_protocols = vec![b"fancyprotocol".to_vec()];
let _connector = super::ConnectorBuilder::new()
.with_tls_config(config_with_alpn)
.https_only()
.enable_http1()
.build();
}
#[test]
#[cfg(all(feature = "http1", feature = "http2"))]
fn test_alpn() {
ensure_global_state();
let roots = rustls::RootCertStore::empty();
let tls_config = rustls::ClientConfig::builder()
.with_root_certificates(roots)
.with_no_client_auth();
let connector = super::ConnectorBuilder::new()
.with_tls_config(tls_config.clone())
.https_only()
.enable_http1()
.build();
assert!(connector
.tls_config
.alpn_protocols
.is_empty());
let connector = super::ConnectorBuilder::new()
.with_tls_config(tls_config.clone())
.https_only()
.enable_http2()
.build();
assert_eq!(&connector.tls_config.alpn_protocols, &[b"h2".to_vec()]);
let connector = super::ConnectorBuilder::new()
.with_tls_config(tls_config.clone())
.https_only()
.enable_http1()
.enable_http2()
.build();
assert_eq!(
&connector.tls_config.alpn_protocols,
&[b"h2".to_vec(), b"http/1.1".to_vec()]
);
let connector = super::ConnectorBuilder::new()
.with_tls_config(tls_config)
.https_only()
.enable_all_versions()
.build();
assert_eq!(
&connector.tls_config.alpn_protocols,
&[b"h2".to_vec(), b"http/1.1".to_vec()]
);
}
#[test]
#[cfg(all(not(feature = "http1"), feature = "http2"))]
fn test_alpn_http2() {
let roots = rustls::RootCertStore::empty();
let tls_config = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(roots)
.with_no_client_auth();
let connector = super::ConnectorBuilder::new()
.with_tls_config(tls_config.clone())
.https_only()
.enable_http2()
.build();
assert_eq!(&connector.tls_config.alpn_protocols, &[b"h2".to_vec()]);
let connector = super::ConnectorBuilder::new()
.with_tls_config(tls_config)
.https_only()
.enable_all_versions()
.build();
assert_eq!(&connector.tls_config.alpn_protocols, &[b"h2".to_vec()]);
}
fn ensure_global_state() {
#[cfg(feature = "ring")]
let _ = rustls::crypto::ring::default_provider().install_default();
#[cfg(feature = "aws-lc-rs")]
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
}
}

76
vendor/hyper-rustls/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,76 @@
//! # hyper-rustls
//!
//! A pure-Rust HTTPS connector for [hyper](https://hyper.rs), based on
//! [Rustls](https://github.com/rustls/rustls).
//!
//! ## Example client
//!
//! ```no_run
//! # #[cfg(all(feature = "rustls-native-certs", feature = "http1"))]
//! # fn main() {
//! use http::StatusCode;
//! use http_body_util::Empty;
//! use hyper::body::Bytes;
//! use hyper_util::client::legacy::Client;
//! use hyper_util::rt::TokioExecutor;
//!
//! let mut rt = tokio::runtime::Runtime::new().unwrap();
//! let url = ("https://hyper.rs").parse().unwrap();
//! let https = hyper_rustls::HttpsConnectorBuilder::new()
//! .with_native_roots()
//! .expect("no native root CA certificates found")
//! .https_only()
//! .enable_http1()
//! .build();
//!
//! let client: Client<_, Empty<Bytes>> = Client::builder(TokioExecutor::new()).build(https);
//!
//! let res = rt.block_on(client.get(url)).unwrap();
//! assert_eq!(res.status(), StatusCode::OK);
//! # }
//! # #[cfg(not(all(feature = "rustls-native-certs", feature = "http1")))]
//! # fn main() {}
//! ```
#![warn(missing_docs, unreachable_pub, clippy::use_self)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
mod config;
mod connector;
mod stream;
#[cfg(feature = "logging")]
mod log {
#[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))]
pub(crate) use log::debug;
#[cfg(feature = "rustls-native-certs")]
pub(crate) use log::warn;
}
#[cfg(not(feature = "logging"))]
mod log {
#[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))]
macro_rules! debug ( ($($tt:tt)*) => {{}} );
#[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))]
pub(crate) use debug;
#[cfg(feature = "rustls-native-certs")]
macro_rules! warn_ ( ($($tt:tt)*) => {{}} );
#[cfg(feature = "rustls-native-certs")]
pub(crate) use warn_ as warn;
}
pub use crate::config::ConfigBuilderExt;
pub use crate::connector::builder::ConnectorBuilder as HttpsConnectorBuilder;
pub use crate::connector::{
DefaultServerNameResolver, FixedServerNameResolver, HttpsConnector, ResolveServerName,
};
pub use crate::stream::MaybeHttpsStream;
/// The various states of the [`HttpsConnectorBuilder`]
pub mod builderstates {
#[cfg(feature = "http2")]
pub use crate::connector::builder::WantsProtocols3;
pub use crate::connector::builder::{
WantsProtocols1, WantsProtocols2, WantsSchemes, WantsTlsConfig,
};
}

121
vendor/hyper-rustls/src/stream.rs vendored Normal file
View File

@@ -0,0 +1,121 @@
// Copied from hyperium/hyper-tls#62e3376/src/stream.rs
use std::fmt;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
use hyper::rt;
use hyper_util::client::legacy::connect::{Connected, Connection};
use hyper_util::rt::TokioIo;
use tokio_rustls::client::TlsStream;
/// A stream that might be protected with TLS.
#[allow(clippy::large_enum_variant)]
pub enum MaybeHttpsStream<T> {
/// A stream over plain text.
Http(T),
/// A stream protected with TLS.
Https(TokioIo<TlsStream<TokioIo<T>>>),
}
impl<T: rt::Read + rt::Write + Connection + Unpin> Connection for MaybeHttpsStream<T> {
fn connected(&self) -> Connected {
match self {
Self::Http(s) => s.connected(),
Self::Https(s) => {
let (tcp, tls) = s.inner().get_ref();
if tls.alpn_protocol() == Some(b"h2") {
tcp.inner().connected().negotiated_h2()
} else {
tcp.inner().connected()
}
}
}
}
}
impl<T: fmt::Debug> fmt::Debug for MaybeHttpsStream<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Http(..) => f.pad("Http(..)"),
Self::Https(..) => f.pad("Https(..)"),
}
}
}
impl<T> From<T> for MaybeHttpsStream<T> {
fn from(inner: T) -> Self {
Self::Http(inner)
}
}
impl<T> From<TlsStream<TokioIo<T>>> for MaybeHttpsStream<T> {
fn from(inner: TlsStream<TokioIo<T>>) -> Self {
Self::Https(TokioIo::new(inner))
}
}
impl<T: rt::Read + rt::Write + Unpin> rt::Read for MaybeHttpsStream<T> {
#[inline]
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context,
buf: rt::ReadBufCursor<'_>,
) -> Poll<Result<(), io::Error>> {
match Pin::get_mut(self) {
Self::Http(s) => Pin::new(s).poll_read(cx, buf),
Self::Https(s) => Pin::new(s).poll_read(cx, buf),
}
}
}
impl<T: rt::Write + rt::Read + Unpin> rt::Write for MaybeHttpsStream<T> {
#[inline]
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize, io::Error>> {
match Pin::get_mut(self) {
Self::Http(s) => Pin::new(s).poll_write(cx, buf),
Self::Https(s) => Pin::new(s).poll_write(cx, buf),
}
}
#[inline]
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
match Pin::get_mut(self) {
Self::Http(s) => Pin::new(s).poll_flush(cx),
Self::Https(s) => Pin::new(s).poll_flush(cx),
}
}
#[inline]
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
match Pin::get_mut(self) {
Self::Http(s) => Pin::new(s).poll_shutdown(cx),
Self::Https(s) => Pin::new(s).poll_shutdown(cx),
}
}
#[inline]
fn is_write_vectored(&self) -> bool {
match self {
Self::Http(s) => s.is_write_vectored(),
Self::Https(s) => s.is_write_vectored(),
}
}
#[inline]
fn poll_write_vectored(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[io::IoSlice<'_>],
) -> Poll<Result<usize, io::Error>> {
match Pin::get_mut(self) {
Self::Http(s) => Pin::new(s).poll_write_vectored(cx, bufs),
Self::Https(s) => Pin::new(s).poll_write_vectored(cx, bufs),
}
}
}

Binary file not shown.

File diff suppressed because one or more lines are too long

102
vendor/hyper-rustls/tests/tests.rs vendored Normal file
View File

@@ -0,0 +1,102 @@
use std::env;
use std::net::TcpStream;
use std::path::PathBuf;
use std::process::Command;
use std::thread;
use std::time;
fn examples_dir() -> PathBuf {
let target_dir: PathBuf = env::var("CARGO_TARGET_DIR")
.unwrap_or_else(|_| "target".to_string())
.into();
target_dir
.join("debug")
.join("examples")
}
fn server_command() -> Command {
Command::new(examples_dir().join("server"))
}
fn client_command() -> Command {
Command::new(examples_dir().join("client"))
}
fn wait_for_server(addr: &str) {
for i in 0..10 {
if TcpStream::connect(addr).is_ok() {
return;
}
thread::sleep(time::Duration::from_millis(i * 100));
}
panic!("failed to connect to {:?} after 10 tries", addr);
}
#[test]
fn client() {
let rc = client_command()
.arg("https://google.com")
.output()
.expect("cannot run client example");
assert!(rc.status.success());
}
#[test]
fn server() {
let mut srv = server_command()
.arg("1337")
.spawn()
.expect("cannot run server example");
let addr = "localhost:1337";
wait_for_server(addr);
let output = Command::new("curl")
.arg("--insecure")
.arg("--http1.0")
.arg(format!("https://{}", addr))
.output()
.expect("cannot run curl");
srv.kill().unwrap();
srv.wait()
.expect("failed to wait on server process");
if !output.status.success() {
let version_stdout = Command::new("curl")
.arg("--version")
.output()
.expect("cannot run curl to collect --version")
.stdout;
println!("curl version: {}", String::from_utf8_lossy(&version_stdout));
println!("curl stderr:\n{}", String::from_utf8_lossy(&output.stderr));
}
assert_eq!(String::from_utf8_lossy(&output.stdout), "Try POST /echo\n");
}
#[test]
fn custom_ca_store() {
let mut srv = server_command()
.arg("1338")
.spawn()
.expect("cannot run server example");
let addr = "localhost:1338";
wait_for_server(addr);
let rc = client_command()
.arg(format!("https://{}", addr))
.arg("examples/sample.pem")
.output()
.expect("cannot run client example");
srv.kill().unwrap();
srv.wait()
.expect("failed to wait on server process");
if !rc.status.success() {
assert_eq!(String::from_utf8_lossy(&rc.stdout), "");
}
}