Skip to content

Commit

Permalink
Allows disabling of hostname verification.
Browse files Browse the repository at this point in the history
Forces user to call danger_disable_host_name_verification to make it
clear this isn't a great idea.
  • Loading branch information
nicklan committed May 4, 2017
1 parent 1a1904e commit 2299b0c
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 10 deletions.
6 changes: 6 additions & 0 deletions examples/tlsclient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ Options:
May be used multiple times to offer serveral protocols.
--cache CACHE Save session cache to file CACHE.
--no-tickets Disable session ticket support.
--insecure Allow connections to sites without certs.
--verbose Emit log output.
--mtu MTU Limit outgoing messages to MTU bytes.
--version, -v Show tool version.
Expand All @@ -324,6 +325,7 @@ struct Args {
flag_auth_key: Option<String>,
flag_auth_certs: Option<String>,
arg_hostname: String,
flag_insecure: bool,
}

// TODO: um, well, it turns out that openssl s_client/s_server
Expand Down Expand Up @@ -415,6 +417,10 @@ fn make_config(args: &Args) -> Arc<rustls::ClientConfig> {
config.enable_tickets = false;
}

if args.flag_insecure {
config.danger_disable_host_name_verification();
}

let persist = Box::new(PersistCache::new(&args.flag_cache));

config.set_protocols(&args.flag_proto);
Expand Down
25 changes: 25 additions & 0 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ pub struct ClientConfig {
/// Supported versions, in no particular order. The default
/// is all supported versions.
pub versions: Vec<ProtocolVersion>,

/// Whether to do host name verification or not. WARNING: turning
/// this off is *insecure* as the host will not be verified to be
/// who it says it is.
host_verification: bool,
}

impl ClientConfig {
Expand All @@ -204,6 +209,7 @@ impl ClientConfig {
client_auth_cert_resolver: Box::new(FailResolveClientCert {}),
enable_tickets: true,
versions: vec![ProtocolVersion::TLSv1_3, ProtocolVersion::TLSv1_2],
host_verification: true,
}
}

Expand Down Expand Up @@ -249,6 +255,25 @@ impl ClientConfig {
self.client_auth_cert_resolver = Box::new(AlwaysResolvesClientCert::new_rsa(cert_chain,
&key_der));
}

/// Allow creation of a TLS stream without verification of host
/// names. WARNING: This is a dangerous option to enable, as it
/// will allow any valid certificate for any site to be trusted
/// for any other site. This opens up a major risk of
/// man-in-the-middle attaks.
pub fn danger_disable_host_name_verification(&mut self) {
self.host_verification = false;
}

/// Enable host name verification.
pub fn enable_host_name_verification(&mut self) {
self.host_verification = true;
}

/// Should this connection do host name verification
pub fn do_host_name_verification(&self) -> bool {
self.host_verification
}
}

pub struct ClientHandshakeData {
Expand Down
10 changes: 6 additions & 4 deletions src/client_hs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -839,11 +839,12 @@ fn handle_certificate_verify(sess: &mut ClientSessionImpl,

info!("Server cert is {:?}", sess.handshake_data.server_cert_chain);

// 1. Verify the certificate chain.
// 1. Verify the certificate chain. (unless configured not to)
// 2. Verify their signature on the handshake.
try!(verify::verify_server_cert(&sess.config.root_store,
&sess.handshake_data.server_cert_chain,
&sess.handshake_data.dns_name));
&sess.handshake_data.dns_name,
!sess.config.do_host_name_verification()));

let handshake_hash = sess.handshake_data.transcript.get_current_hash();
try!(verify::verify_tls13(&sess.handshake_data.server_cert_chain[0],
Expand Down Expand Up @@ -1076,7 +1077,7 @@ fn handle_server_hello_done(sess: &mut ClientSessionImpl,
info!("Server cert is {:?}", sess.handshake_data.server_cert_chain);
info!("Server DNS name is {:?}", sess.handshake_data.dns_name);

// 1. Verify the cert chain.
// 1. Verify the cert chain. (unless configured not to)
// 2. Verify that the top certificate signed their kx.
// 3. If doing client auth, send our Certificate.
// 4. Complete the key exchange:
Expand All @@ -1090,7 +1091,8 @@ fn handle_server_hello_done(sess: &mut ClientSessionImpl,
// 1.
try!(verify::verify_server_cert(&sess.config.root_store,
&sess.handshake_data.server_cert_chain,
&sess.handshake_data.dns_name));
&sess.handshake_data.dns_name,
!sess.config.do_host_name_verification()));

// 2.
// Build up the contents of the signed message.
Expand Down
14 changes: 8 additions & 6 deletions src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ impl RootCertStore {
/// Return the `webpki::EndEntityCert` for the top certificate
/// in `presented_certs`.
fn verify_common_cert<'a>(roots: &RootCertStore,
presented_certs: &'a [ASN1Cert])
presented_certs: &'a [ASN1Cert],
skip_verify: bool)
-> Result<webpki::EndEntityCert<'a>, TLSError> {
if presented_certs.is_empty() {
return Err(TLSError::NoCertificatesPresented);
Expand All @@ -176,7 +177,7 @@ fn verify_common_cert<'a>(roots: &RootCertStore,
.map(|x| x.to_trust_anchor())
.collect();

if DANGEROUS_DISABLE_VERIFY {
if DANGEROUS_DISABLE_VERIFY || skip_verify {
warn!("DANGEROUS_DISABLE_VERIFY is turned on, skipping certificate verification");
return Ok(cert);
}
Expand All @@ -191,11 +192,12 @@ fn verify_common_cert<'a>(roots: &RootCertStore,
/// the top certificate in the chain.
pub fn verify_server_cert(roots: &RootCertStore,
presented_certs: &[ASN1Cert],
dns_name: &str)
dns_name: &str,
skip_host_name_verify: bool)
-> Result<(), TLSError> {
let cert = try!(verify_common_cert(roots, presented_certs));
let cert = try!(verify_common_cert(roots, presented_certs, skip_host_name_verify));

if DANGEROUS_DISABLE_VERIFY {
if DANGEROUS_DISABLE_VERIFY || skip_host_name_verify {
warn!("DANGEROUS_DISABLE_VERIFY is turned on, skipping server name verification");
return Ok(());
}
Expand All @@ -209,7 +211,7 @@ pub fn verify_server_cert(roots: &RootCertStore,
pub fn verify_client_cert(roots: &RootCertStore,
presented_certs: &[ASN1Cert])
-> Result<(), TLSError> {
verify_common_cert(roots, presented_certs).map(|_| ())
verify_common_cert(roots, presented_certs, false).map(|_| ())
}

static ECDSA_SHA256: SignatureAlgorithms = &[&webpki::ECDSA_P256_SHA256,
Expand Down

0 comments on commit 2299b0c

Please sign in to comment.