mirror of https://github.com/ctz/rustls
Add tests for dangerous_configuration
Also: - use it for bogo_shim, which previously used DANGEROUS_DISABLE_VERIFY. bogo_shim now only built with dangerous_configuration. - require a non-empty certificate list outside the external verifier; this is a internal invariant. - Abolish ASN1Cert in preference to key::Certificate
This commit is contained in:
parent
0c066ba125
commit
46d5fc03a5
|
@ -13,6 +13,7 @@ before_install:
|
|||
script:
|
||||
- cargo build
|
||||
- RUST_BACKTRACE=1 cargo test
|
||||
- RUST_BACKTRACE=1 cargo test --features dangerous_configuration danger
|
||||
- cargo test --release --no-run
|
||||
- ./target/release/examples/bench
|
||||
- ( cd trytls && ./runme )
|
||||
|
|
|
@ -34,6 +34,7 @@ regex = "0.2"
|
|||
[[example]]
|
||||
name = "bogo_shim"
|
||||
path = "examples/internal/bogo_shim.rs"
|
||||
required-features = ["dangerous_configuration"]
|
||||
|
||||
[[example]]
|
||||
name = "trytls_shim"
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
|
||||
set -xe
|
||||
|
||||
cp ../src/verify.rs ../src/verify-secure.rs
|
||||
sed -i -e 's/\(DANGEROUS_DISABLE_VERIFY: bool = \)false/\1true/g' ../src/verify.rs
|
||||
cargo test --no-run
|
||||
cargo test --no-run --features dangerous_configuration
|
||||
|
||||
if [ ! -e bogo/ ] ; then
|
||||
./fetch-and-build
|
||||
|
@ -17,4 +15,3 @@ fi
|
|||
-shim-config ../config.json \
|
||||
-test.parallel 1 -num-workers 1 \
|
||||
-pipe -allow-unimplemented )
|
||||
mv ../src/verify-secure.rs ../src/verify.rs
|
||||
|
|
|
@ -116,6 +116,27 @@ fn split_protocols(protos: &str) -> Vec<String> {
|
|||
ret
|
||||
}
|
||||
|
||||
struct NoVerification {}
|
||||
|
||||
impl rustls::ClientCertVerifier for NoVerification {
|
||||
fn verify_client_cert(&self,
|
||||
_roots: &rustls::RootCertStore,
|
||||
_certs: &[rustls::Certificate]) -> Result<(), rustls::TLSError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl rustls::ServerCertVerifier for NoVerification {
|
||||
fn verify_server_cert(&self,
|
||||
_roots: &rustls::RootCertStore,
|
||||
_certs: &[rustls::Certificate],
|
||||
_hostname: &str) -> Result<(), rustls::TLSError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
static NO_VERIFICATION: NoVerification = NoVerification {};
|
||||
|
||||
fn make_server_cfg(opts: &Options) -> Arc<rustls::ServerConfig> {
|
||||
let mut cfg = rustls::ServerConfig::new();
|
||||
let persist = rustls::ServerSessionMemoryCache::new(32);
|
||||
|
@ -125,10 +146,13 @@ fn make_server_cfg(opts: &Options) -> Arc<rustls::ServerConfig> {
|
|||
let key = load_key(&opts.key_file.replace(".pem", ".rsa"));
|
||||
cfg.set_single_cert(cert.clone(), key);
|
||||
|
||||
if opts.offer_no_client_cas {
|
||||
cfg.client_auth_offer = true;
|
||||
} else if opts.require_any_client_cert {
|
||||
if opts.offer_no_client_cas || opts.require_any_client_cert {
|
||||
cfg.client_auth_offer = true;
|
||||
cfg.dangerous()
|
||||
.set_certificate_verifier(&NO_VERIFICATION);
|
||||
}
|
||||
|
||||
if opts.require_any_client_cert {
|
||||
cfg.client_auth_mandatory = true;
|
||||
}
|
||||
|
||||
|
@ -165,6 +189,9 @@ fn make_client_cfg(opts: &Options) -> Arc<rustls::ClientConfig> {
|
|||
cfg.set_single_client_cert(cert, key);
|
||||
}
|
||||
|
||||
cfg.dangerous()
|
||||
.set_certificate_verifier(&NO_VERIFICATION);
|
||||
|
||||
if !opts.protocols.is_empty() {
|
||||
cfg.set_protocols(&opts.protocols);
|
||||
}
|
||||
|
|
|
@ -840,13 +840,17 @@ fn handle_certificate_verify(sess: &mut ClientSessionImpl,
|
|||
info!("Server cert is {:?}", sess.handshake_data.server_cert_chain);
|
||||
|
||||
// 1. Verify the certificate chain.
|
||||
// 2. Verify their signature on the handshake.
|
||||
if sess.handshake_data.server_cert_chain.is_empty() {
|
||||
return Err(TLSError::NoCertificatesPresented);
|
||||
}
|
||||
|
||||
try! {
|
||||
sess.config.get_verifier().verify_server_cert(&sess.config.root_store,
|
||||
&sess.handshake_data.server_cert_chain,
|
||||
&sess.handshake_data.dns_name)
|
||||
};
|
||||
|
||||
// 2. Verify their signature on the handshake.
|
||||
let handshake_hash = sess.handshake_data.transcript.get_current_hash();
|
||||
try! {
|
||||
verify::verify_tls13(&sess.handshake_data.server_cert_chain[0],
|
||||
|
@ -1092,6 +1096,10 @@ fn handle_server_hello_done(sess: &mut ClientSessionImpl,
|
|||
// 5. emit a Finished, our first encrypted message under the new keys.
|
||||
|
||||
// 1.
|
||||
if sess.handshake_data.server_cert_chain.is_empty() {
|
||||
return Err(TLSError::NoCertificatesPresented);
|
||||
}
|
||||
|
||||
try! {
|
||||
sess.config.get_verifier().verify_server_cert(&sess.config.root_store,
|
||||
&sess.handshake_data.server_cert_chain,
|
||||
|
|
|
@ -1159,7 +1159,6 @@ impl ServerHelloPayload {
|
|||
}
|
||||
}
|
||||
|
||||
pub type ASN1Cert = key::Certificate;
|
||||
pub type CertificatePayload = Vec<key::Certificate>;
|
||||
|
||||
impl Codec for CertificatePayload {
|
||||
|
@ -1218,7 +1217,7 @@ declare_u16_vec!(CertificateExtensions, CertificateExtension);
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct CertificateEntry {
|
||||
pub cert: ASN1Cert,
|
||||
pub cert: key::Certificate,
|
||||
pub exts: CertificateExtensions,
|
||||
}
|
||||
|
||||
|
@ -1230,14 +1229,14 @@ impl Codec for CertificateEntry {
|
|||
|
||||
fn read(r: &mut Reader) -> Option<CertificateEntry> {
|
||||
Some(CertificateEntry {
|
||||
cert: try_ret!(ASN1Cert::read(r)),
|
||||
cert: try_ret!(key::Certificate::read(r)),
|
||||
exts: try_ret!(CertificateExtensions::read(r)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl CertificateEntry {
|
||||
pub fn new(cert: ASN1Cert) -> CertificateEntry {
|
||||
pub fn new(cert: key::Certificate) -> CertificateEntry {
|
||||
CertificateEntry {
|
||||
cert: cert,
|
||||
exts: Vec::new(),
|
||||
|
|
|
@ -2,7 +2,7 @@ use webpki;
|
|||
use time;
|
||||
use untrusted;
|
||||
|
||||
use msgs::handshake::ASN1Cert;
|
||||
use key::Certificate;
|
||||
use msgs::handshake::DigitallySignedStruct;
|
||||
use msgs::enums::SignatureScheme;
|
||||
use error::TLSError;
|
||||
|
@ -32,7 +32,7 @@ pub trait ServerCertVerifier : Send + Sync {
|
|||
/// the top certificate in the chain.
|
||||
fn verify_server_cert(&self,
|
||||
roots: &RootCertStore,
|
||||
presented_certs: &[ASN1Cert],
|
||||
presented_certs: &[Certificate],
|
||||
dns_name: &str) -> Result<(), TLSError>;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ pub trait ClientCertVerifier : Send + Sync {
|
|||
/// Does no further checking of the certificate.
|
||||
fn verify_client_cert(&self,
|
||||
roots: &RootCertStore,
|
||||
presented_certs: &[ASN1Cert]) -> Result<(), TLSError>;
|
||||
presented_certs: &[Certificate]) -> Result<(), TLSError>;
|
||||
}
|
||||
|
||||
pub struct WebPKIVerifier {}
|
||||
|
@ -51,7 +51,7 @@ pub static WEB_PKI: WebPKIVerifier = WebPKIVerifier {};
|
|||
impl ServerCertVerifier for WebPKIVerifier {
|
||||
fn verify_server_cert(&self,
|
||||
roots: &RootCertStore,
|
||||
presented_certs: &[ASN1Cert],
|
||||
presented_certs: &[Certificate],
|
||||
dns_name: &str) -> Result<(), TLSError> {
|
||||
let cert = try!(self.verify_common_cert(roots, presented_certs));
|
||||
|
||||
|
@ -63,7 +63,7 @@ impl ServerCertVerifier for WebPKIVerifier {
|
|||
impl ClientCertVerifier for WebPKIVerifier {
|
||||
fn verify_client_cert(&self,
|
||||
roots: &RootCertStore,
|
||||
presented_certs: &[ASN1Cert]) -> Result<(), TLSError> {
|
||||
presented_certs: &[Certificate]) -> Result<(), TLSError> {
|
||||
self.verify_common_cert(roots, presented_certs).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ impl WebPKIVerifier {
|
|||
/// in `presented_certs`.
|
||||
fn verify_common_cert<'a>(&self,
|
||||
roots: &RootCertStore,
|
||||
presented_certs: &'a [ASN1Cert])
|
||||
presented_certs: &'a [Certificate])
|
||||
-> Result<webpki::EndEntityCert<'a>, TLSError> {
|
||||
if presented_certs.is_empty() {
|
||||
return Err(TLSError::NoCertificatesPresented);
|
||||
|
@ -163,7 +163,7 @@ fn verify_sig_using_any_alg(cert: &webpki::EndEntityCert,
|
|||
/// `cert` MUST have been authenticated before using this function,
|
||||
/// typically using `verify_cert`.
|
||||
pub fn verify_signed_struct(message: &[u8],
|
||||
cert: &ASN1Cert,
|
||||
cert: &Certificate,
|
||||
dss: &DigitallySignedStruct)
|
||||
-> Result<(), TLSError> {
|
||||
|
||||
|
@ -195,7 +195,7 @@ fn convert_alg_tls13(scheme: SignatureScheme)
|
|||
}
|
||||
}
|
||||
|
||||
pub fn verify_tls13(cert: &ASN1Cert,
|
||||
pub fn verify_tls13(cert: &Certificate,
|
||||
dss: &DigitallySignedStruct,
|
||||
handshake_hash: &[u8],
|
||||
context_string_with_0: &[u8])
|
||||
|
|
|
@ -148,4 +148,16 @@ mod online {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "dangerous_configuration")]
|
||||
mod danger {
|
||||
#[test]
|
||||
fn self_signed() {
|
||||
super::polite();
|
||||
super::connect("self-signed.badssl.com")
|
||||
.insecure()
|
||||
.expect("<title>self-signed.badssl.com</title>")
|
||||
.go()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@ pub struct TlsClient {
|
|||
pub suites: Vec<String>,
|
||||
pub protos: Vec<String>,
|
||||
pub no_tickets: bool,
|
||||
pub insecure: bool,
|
||||
pub verbose: bool,
|
||||
pub mtu: Option<usize>,
|
||||
pub expect_fails: bool,
|
||||
|
@ -131,6 +132,7 @@ impl TlsClient {
|
|||
client_auth_certs: None,
|
||||
cache: None,
|
||||
no_tickets: false,
|
||||
insecure: false,
|
||||
verbose: false,
|
||||
mtu: None,
|
||||
suites: Vec::new(),
|
||||
|
@ -162,6 +164,11 @@ impl TlsClient {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn insecure(&mut self) -> &mut TlsClient {
|
||||
self.insecure = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn verbose(&mut self) -> &mut TlsClient {
|
||||
self.verbose = true;
|
||||
self
|
||||
|
@ -225,6 +232,10 @@ impl TlsClient {
|
|||
args.push("--no-tickets");
|
||||
}
|
||||
|
||||
if self.insecure {
|
||||
args.push("--insecure");
|
||||
}
|
||||
|
||||
if self.cafile.is_some() {
|
||||
args.push("--cafile");
|
||||
args.push(self.cafile.as_ref().unwrap());
|
||||
|
|
Loading…
Reference in New Issue