Skip to content

Commit 758651d

Browse files
Add client certificate validation.
Related to sfackler#161 Co-authored-by: Aleksei Volkov <[email protected]>
1 parent 481b979 commit 758651d

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

src/imp/openssl.rs

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

19-
use {Protocol, TlsAcceptorBuilder, TlsConnectorBuilder};
19+
20+
use {Protocol, TlsAcceptorBuilder, TlsConnectorBuilder, TlsClientCertificateVerification};
2021

2122
#[cfg(have_min_max_version)]
2223
fn supported_protocols(
@@ -365,6 +366,20 @@ impl TlsAcceptor {
365366
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
366367
acceptor.set_private_key(&builder.identity.0.pkey)?;
367368
acceptor.set_certificate(&builder.identity.0.cert)?;
369+
370+
if let Some(client_ca_cert) = &builder.client_cert_verification_ca_cert {
371+
if builder.client_cert_verification_trust {
372+
acceptor.cert_store_mut().add_cert((client_ca_cert.0).0.to_owned())?;
373+
}
374+
acceptor.add_client_ca((client_ca_cert.0).0.as_ref())?;
375+
}
376+
let verify_mode = match &builder.client_cert_verification {
377+
TlsClientCertificateVerification::DoNotRequestCertificate => SslVerifyMode::NONE,
378+
TlsClientCertificateVerification::RequestCertificate => SslVerifyMode::PEER,
379+
TlsClientCertificateVerification::RequireCertificate => SslVerifyMode::PEER | SslVerifyMode::FAIL_IF_NO_PEER_CERT,
380+
};
381+
acceptor.set_verify(verify_mode);
382+
368383
for cert in builder.identity.0.chain.iter() {
369384
// https://www.openssl.org/docs/manmaster/man3/SSL_CTX_add_extra_chain_cert.html
370385
// specifies that "When sending a certificate chain, extra chain certificates are

src/lib.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,13 +507,31 @@ impl TlsConnector {
507507
}
508508
}
509509

510+
/// Client certificate verification modes
511+
pub enum TlsClientCertificateVerification {
512+
/// The server will not request certificates from the client.
513+
///
514+
/// # Warning
515+
/// The client will not be able to send any certificates with this setting.
516+
DoNotRequestCertificate,
517+
/// The server will request a certificate from the client, then will validate
518+
/// any certificate it receives. The client may choose not to send any.
519+
RequestCertificate,
520+
/// The server will request a certificate from the client, then will validate
521+
/// any certificate it receives or reject the connection none are provided.
522+
RequireCertificate,
523+
}
524+
510525
/// A builder for `TlsAcceptor`s.
511526
///
512527
/// You can get one from [`TlsAcceptor::builder()`](TlsAcceptor::builder)
513528
pub struct TlsAcceptorBuilder {
514529
identity: Identity,
515530
min_protocol: Option<Protocol>,
516531
max_protocol: Option<Protocol>,
532+
client_cert_verification: TlsClientCertificateVerification,
533+
client_cert_verification_ca_cert: Option<Certificate>,
534+
client_cert_verification_trust: bool
517535
}
518536

519537
impl TlsAcceptorBuilder {
@@ -537,6 +555,35 @@ impl TlsAcceptorBuilder {
537555
self
538556
}
539557

558+
/// Sets the verification mode for client certificates.
559+
///
560+
/// Defaults to `TlsClientCertificateVerification::DoNotRequestCertificate`.
561+
pub fn client_cert_verification(&mut self, client_cert_verification: TlsClientCertificateVerification) -> &mut TlsAcceptorBuilder {
562+
self.client_cert_verification = client_cert_verification;
563+
self
564+
}
565+
566+
/// Sets which ca to tell the client is acceptable to send to the server.
567+
///
568+
/// A value of `None` will not tell the client it is acceptable to send certificates signed by any ca.
569+
///
570+
/// Defaults `None`.
571+
pub fn client_cert_verification_ca_cert(&mut self, client_cert_verification_ca_cert: Option<Certificate>) -> &mut TlsAcceptorBuilder {
572+
self.client_cert_verification_ca_cert = client_cert_verification_ca_cert;
573+
self
574+
}
575+
576+
/// Trust the ca certificate used for client verification
577+
///
578+
/// Adds client ca to the list of trusted certificates. This is used in
579+
/// case you are using self-signed CA certificate.
580+
///
581+
/// Defaults `false`
582+
pub fn trust_client_ca_cert(&mut self, should_trust: bool) -> &mut TlsAcceptorBuilder {
583+
self.client_cert_verification_trust = should_trust;
584+
self
585+
}
586+
540587
/// Creates a new `TlsAcceptor`.
541588
pub fn build(&self) -> Result<TlsAcceptor> {
542589
let acceptor = imp::TlsAcceptor::new(self)?;
@@ -601,6 +648,9 @@ impl TlsAcceptor {
601648
identity,
602649
min_protocol: Some(Protocol::Tlsv10),
603650
max_protocol: None,
651+
client_cert_verification: TlsClientCertificateVerification::DoNotRequestCertificate,
652+
client_cert_verification_ca_cert: None,
653+
client_cert_verification_trust: false
604654
}
605655
}
606656

0 commit comments

Comments
 (0)