Skip to content
This repository was archived by the owner on Feb 9, 2025. It is now read-only.

Commit b4c5e93

Browse files
committed
Add client certificate validation.
Related to sfackler#161
1 parent 75e43da commit b4c5e93

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

src/imp/openssl.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::fmt;
1616
use std::io;
1717
use std::sync::Once;
1818

19-
use {Protocol, TlsAcceptorBuilder, TlsConnectorBuilder};
19+
use {Protocol, TlsAcceptorBuilder, TlsConnectorBuilder, TlsClientCertificateVerification};
2020
use self::openssl::pkey::Private;
2121

2222
#[cfg(have_min_max_version)]
@@ -307,6 +307,17 @@ impl TlsAcceptor {
307307
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
308308
acceptor.set_private_key(&builder.identity.0.pkey)?;
309309
acceptor.set_certificate(&builder.identity.0.cert)?;
310+
311+
if let Some(client_ca_cert) = &builder.client_cert_verification_ca_cert {
312+
acceptor.add_client_ca((client_ca_cert.0).0.as_ref())?;
313+
}
314+
let verify_mode = match &builder.client_cert_verification {
315+
TlsClientCertificateVerification::DoNotRequestCertificate => SslVerifyMode::NONE,
316+
TlsClientCertificateVerification::RequestCertificate => SslVerifyMode::PEER,
317+
TlsClientCertificateVerification::RequireCertificate => SslVerifyMode::PEER | SslVerifyMode::FAIL_IF_NO_PEER_CERT,
318+
};
319+
acceptor.set_verify(verify_mode);
320+
310321
for cert in builder.identity.0.chain.iter().rev() {
311322
acceptor.add_extra_chain_cert(cert.to_owned())?;
312323
}

src/lib.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,11 +482,30 @@ impl TlsConnector {
482482
}
483483
}
484484

485+
/// Client certificate verification modes
486+
pub enum TlsClientCertificateVerification {
487+
/// The server will not request certificates from the client.
488+
///
489+
/// # Warning
490+
/// The client will not be able to send any certificates with this setting.
491+
DoNotRequestCertificate,
492+
/// The server will request a certificate from the client, then will validate
493+
/// any certificate it receives. The client may choose not to send any.
494+
RequestCertificate,
495+
/// The server will request a certificate from the client, then will validate
496+
/// any certificate it receives or reject the connection none are provided.
497+
RequireCertificate,
498+
}
499+
485500
/// A builder for `TlsAcceptor`s.
486501
pub struct TlsAcceptorBuilder {
487502
identity: Identity,
488503
min_protocol: Option<Protocol>,
489504
max_protocol: Option<Protocol>,
505+
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
506+
client_cert_verification: TlsClientCertificateVerification,
507+
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
508+
client_cert_verification_ca_cert: Option<Certificate>
490509
}
491510

492511
impl TlsAcceptorBuilder {
@@ -510,6 +529,26 @@ impl TlsAcceptorBuilder {
510529
self
511530
}
512531

532+
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
533+
/// Sets the verification mode for client certificates.
534+
///
535+
/// Defaults to `TlsClientCertificateVerification::DoNotRequestCertificate`.
536+
pub fn client_cert_verification(&mut self, client_cert_verification: TlsClientCertificateVerification) -> &mut TlsAcceptorBuilder {
537+
self.client_cert_verification = client_cert_verification;
538+
self
539+
}
540+
541+
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
542+
/// Sets which ca to tell the client is acceptable to send to the server.
543+
///
544+
/// A value of `None` will not tell the client it is acceptable to send certificates signed by any ca.
545+
///
546+
/// Defaults `None`.
547+
pub fn client_cert_verification_ca_cert(&mut self, client_cert_verification_ca_cert: Option<Certificate>) -> &mut TlsAcceptorBuilder {
548+
self.client_cert_verification_ca_cert = client_cert_verification_ca_cert;
549+
self
550+
}
551+
513552
/// Creates a new `TlsAcceptor`.
514553
pub fn build(&self) -> Result<TlsAcceptor> {
515554
let acceptor = imp::TlsAcceptor::new(self)?;
@@ -574,6 +613,10 @@ impl TlsAcceptor {
574613
identity,
575614
min_protocol: Some(Protocol::Tlsv10),
576615
max_protocol: None,
616+
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
617+
client_cert_verification: TlsClientCertificateVerification::DoNotRequestCertificate,
618+
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
619+
client_cert_verification_ca_cert: None
577620
}
578621
}
579622

0 commit comments

Comments
 (0)