tls_api_test/
lib.rs

1//! Common implementation of tests for all TLS API implementations.
2//!
3//! Common tests are written here and executed in impl-crates.
4//!
5//! Probably you don't need this crate outside of `rust-tls-api` repository.
6
7#![cfg_attr(rustc_nightly, feature(test))]
8
9#[macro_use]
10extern crate log;
11
12#[cfg(rustc_nightly)]
13extern crate test;
14
15use std::any;
16use std::str;
17
18#[macro_use]
19mod t;
20
21mod alpn;
22pub mod benches;
23mod client_server;
24mod client_server_dyn;
25mod google;
26mod version;
27
28pub use alpn::test_alpn;
29pub use client_server::test_client_server_der;
30pub use client_server::test_client_server_pkcs12;
31pub use client_server_dyn::test_client_server_dyn_der;
32pub use client_server_dyn::test_client_server_dyn_pkcs12;
33pub use google::test_google;
34pub use version::test_version;
35
36mod gen;
37pub use gen::gen_tests_and_benches;
38
39mod gen_rustc_nightly;
40pub(crate) use gen_rustc_nightly::gen_rustc_nightly;
41
42use tls_api::TlsAcceptor;
43use tls_api::TlsAcceptorBox;
44use tls_api::TlsAcceptorBuilder;
45use tls_api::TlsAcceptorBuilderBox;
46use tls_api::TlsAcceptorType;
47use tls_api::TlsConnector;
48use tls_api::TlsConnectorBox;
49use tls_api::TlsConnectorBuilder;
50use tls_api::TlsConnectorBuilderBox;
51use tls_api::TlsConnectorType;
52
53use std::net::ToSocketAddrs;
54
55#[cfg(feature = "runtime-async-std")]
56pub use async_std::net::TcpListener;
57#[cfg(feature = "runtime-async-std")]
58pub use async_std::net::TcpStream;
59
60#[cfg(feature = "runtime-tokio")]
61pub use tokio::net::TcpListener;
62#[cfg(feature = "runtime-tokio")]
63pub use tokio::net::TcpStream;
64
65#[cfg(feature = "runtime-async-std")]
66pub use async_std::task::block_on;
67
68#[cfg(feature = "runtime-tokio")]
69pub fn block_on<F, T>(future: F) -> T
70where
71    F: std::future::Future<Output = T>,
72{
73    t!(tokio::runtime::Runtime::new()).block_on(future)
74}
75
76async fn connect_bad_hostname_impl<C: TlsConnector, F: FnOnce(anyhow::Error)>(check_error: F) {
77    drop(env_logger::try_init());
78
79    if !C::IMPLEMENTED {
80        eprintln!(
81            "connector {} is not implemented; skipping",
82            any::type_name::<C>()
83        );
84        return;
85    }
86
87    // First up, resolve google.com
88    let addr = t!("google.com:443".to_socket_addrs()).next().unwrap();
89
90    let connector: C = C::builder().expect("builder").build().expect("build");
91    let tcp_stream = t!(TcpStream::connect(addr).await);
92    let error = connector
93        .connect("goggle.com", tcp_stream)
94        .await
95        .unwrap_err();
96    check_error(error);
97}
98
99pub fn connect_bad_hostname<C: TlsConnector, F: FnOnce(anyhow::Error)>(check_error: F) {
100    block_on(connect_bad_hostname_impl::<C, F>(check_error))
101}
102
103async fn connect_bad_hostname_ignored_impl<C: TlsConnector>() {
104    drop(env_logger::try_init());
105
106    if !C::IMPLEMENTED {
107        eprintln!(
108            "connector {} is not implemented; skipping",
109            any::type_name::<C>()
110        );
111        return;
112    }
113
114    // First up, resolve google.com
115    let addr = t!("google.com:443".to_socket_addrs()).next().unwrap();
116
117    let tcp_stream = t!(TcpStream::connect(addr).await);
118
119    let mut builder = C::builder().expect("builder");
120    builder
121        .set_verify_hostname(false)
122        .expect("set_verify_hostname");
123    let connector: C = builder.build().expect("build");
124    t!(connector.connect("ignore", tcp_stream).await);
125}
126
127pub fn connect_bad_hostname_ignored<C: TlsConnector>() {
128    block_on(connect_bad_hostname_ignored_impl::<C>())
129}
130
131fn new_acceptor_builder_from_pkcs12_keys<A>() -> A::Builder
132where
133    A: TlsAcceptor,
134{
135    t!(A::builder_from_pkcs12(
136        &test_cert_gen::keys().server.cert_and_key_pkcs12.pkcs12.0,
137        &test_cert_gen::keys().server.cert_and_key_pkcs12.password,
138    ))
139}
140
141fn new_acceptor_builder_from_der_keys<A>() -> A::Builder
142where
143    A: TlsAcceptor,
144{
145    let keys = &test_cert_gen::keys().server.cert_and_key;
146    t!(A::builder_from_der_key(
147        keys.cert.get_der(),
148        keys.key.get_der()
149    ))
150}
151
152fn new_acceptor_from_der_keys<A: TlsAcceptor>() -> A {
153    new_acceptor_builder_from_der_keys::<A>().build().unwrap()
154}
155
156fn new_acceptor_builder_dyn_from_pkcs12_keys(
157    acceptor: &dyn TlsAcceptorType,
158) -> TlsAcceptorBuilderBox {
159    t!(acceptor.builder_from_pkcs12(
160        &test_cert_gen::keys().server.cert_and_key_pkcs12.pkcs12.0,
161        &test_cert_gen::keys().server.cert_and_key_pkcs12.password,
162    ))
163}
164
165fn new_acceptor_builder_dyn_from_der_keys(acceptor: &dyn TlsAcceptorType) -> TlsAcceptorBuilderBox {
166    let keys = &test_cert_gen::keys().server.cert_and_key;
167    t!(acceptor.builder_from_der_key(keys.cert.get_der(), keys.key.get_der()))
168}
169
170fn new_acceptor_dyn_from_der_keys(acceptor: &dyn TlsAcceptorType) -> TlsAcceptorBox {
171    new_acceptor_builder_dyn_from_der_keys(acceptor)
172        .build()
173        .unwrap()
174}
175
176pub enum AcceptorKeyKind {
177    Pkcs12,
178    Der,
179}
180
181fn new_acceptor<A>(key: Option<AcceptorKeyKind>) -> A::Builder
182where
183    A: TlsAcceptor,
184{
185    match key {
186        Some(AcceptorKeyKind::Der) => new_acceptor_builder_from_der_keys::<A>(),
187        Some(AcceptorKeyKind::Pkcs12) => new_acceptor_builder_from_pkcs12_keys::<A>(),
188        None => {
189            if A::SUPPORTS_PKCS12_KEYS {
190                new_acceptor_builder_from_pkcs12_keys::<A>()
191            } else if A::SUPPORTS_DER_KEYS {
192                new_acceptor_builder_from_der_keys::<A>()
193            } else {
194                panic!(
195                    "no constructor supported for acceptor {}",
196                    any::type_name::<A>()
197                );
198            }
199        }
200    }
201}
202
203fn new_acceptor_dyn(
204    acceptor: &dyn TlsAcceptorType,
205    key: Option<AcceptorKeyKind>,
206) -> TlsAcceptorBuilderBox {
207    match key {
208        Some(AcceptorKeyKind::Der) => new_acceptor_builder_dyn_from_der_keys(acceptor),
209        Some(AcceptorKeyKind::Pkcs12) => new_acceptor_builder_dyn_from_pkcs12_keys(acceptor),
210        None => {
211            if acceptor.supports_pkcs12_keys() {
212                new_acceptor_builder_dyn_from_pkcs12_keys(acceptor)
213            } else if acceptor.supports_der_keys() {
214                new_acceptor_builder_dyn_from_der_keys(acceptor)
215            } else {
216                panic!("no constructor supported for acceptor {}", acceptor);
217            }
218        }
219    }
220}
221
222fn new_connector_builder_with_root_ca<C: TlsConnector>() -> C::Builder {
223    let keys = test_cert_gen::keys();
224    let root_ca = &keys.client.ca;
225
226    let mut connector = C::builder().expect("connector builder");
227    t!(connector.add_root_certificate(root_ca.get_der()));
228    connector
229}
230
231fn new_connector_with_root_ca<C: TlsConnector>() -> C {
232    new_connector_builder_with_root_ca::<C>().build().unwrap()
233}
234
235fn new_connector_builder_dyn_with_root_ca(
236    connector: &dyn TlsConnectorType,
237) -> TlsConnectorBuilderBox {
238    let keys = test_cert_gen::keys();
239    let root_ca = &keys.client.ca;
240
241    let mut connector = connector.builder().expect("connector builder");
242    t!(connector.add_root_certificate(root_ca.get_der()));
243    connector
244}
245
246fn new_connector_dyn_with_root_ca(connector: &dyn TlsConnectorType) -> TlsConnectorBox {
247    new_connector_builder_dyn_with_root_ca(connector)
248        .build()
249        .unwrap()
250}
251
252// `::1` is broken on travis-ci
253// https://travis-ci.org/stepancheg/rust-tls-api/jobs/312681800
254pub const BIND_HOST: &str = "127.0.0.1";