@@ -5,15 +5,17 @@ use std::ptr::null;
5
5
use std:: slice;
6
6
use std:: sync:: Arc ;
7
7
8
- use rustls:: server:: { AllowAnyAnonymousOrAuthenticatedClient , AllowAnyAuthenticatedClient } ;
8
+ use rustls:: server:: {
9
+ AllowAnyAnonymousOrAuthenticatedClient , AllowAnyAuthenticatedClient , UnparsedCertRevocationList ,
10
+ } ;
9
11
use rustls:: sign:: CertifiedKey ;
10
12
use rustls:: {
11
13
Certificate , PrivateKey , RootCertStore , SupportedCipherSuite , ALL_CIPHER_SUITES ,
12
14
DEFAULT_CIPHER_SUITES ,
13
15
} ;
14
- use rustls_pemfile:: { certs, pkcs8_private_keys, rsa_private_keys} ;
16
+ use rustls_pemfile:: { certs, crls , pkcs8_private_keys, rsa_private_keys} ;
15
17
16
- use crate :: error:: rustls_result;
18
+ use crate :: error:: { map_error , rustls_result} ;
17
19
use crate :: rslice:: { rustls_slice_bytes, rustls_str} ;
18
20
use crate :: {
19
21
ffi_panic_boundary, try_box_from_ptr, try_mut_from_ptr, try_ref_from_ptr, try_slice,
@@ -509,6 +511,97 @@ impl rustls_root_cert_store {
509
511
}
510
512
}
511
513
514
+ /// A builder for a `rustls_client_cert_verifier`. This builder object can be used to configure
515
+ /// certificate revocation lists, and then turned into a `rustls_client_cert_verifier` once ready.
516
+ pub struct rustls_client_cert_verifier_builder {
517
+ _private : [ u8 ; 0 ] ,
518
+ }
519
+
520
+ // XXX: contained value is consumed even on error, so this can contain None. but the caller
521
+ // still needs to free it
522
+ pub ( crate ) struct AllowAnyAuthenticatedClientHolder ( Option < AllowAnyAuthenticatedClient > ) ;
523
+
524
+ impl CastPtr for rustls_client_cert_verifier_builder {
525
+ type RustType = AllowAnyAuthenticatedClientHolder ;
526
+ }
527
+
528
+ impl BoxCastPtr for rustls_client_cert_verifier_builder { }
529
+
530
+ impl rustls_client_cert_verifier_builder {
531
+ /// Create a new client certificate verifier builder for the root store.
532
+ ///
533
+ /// This copies the contents of the rustls_root_cert_store. It does not take
534
+ /// ownership of the pointed-to memory.
535
+ ///
536
+ /// This object can then be used to load any CRLs.
537
+ ///
538
+ /// Once that is complete, convert it into a real `rustls_client_cert_verifier`
539
+ /// by calling `rustls_client_cert_verifier_new()`.
540
+ #[ no_mangle]
541
+ pub extern "C" fn rustls_client_cert_verifier_builder_new (
542
+ store : * const rustls_root_cert_store ,
543
+ ) -> * mut rustls_client_cert_verifier_builder {
544
+ ffi_panic_boundary ! {
545
+ let store: & RootCertStore = try_ref_from_ptr!( store) ;
546
+ let client_cert_verifier = AllowAnyAuthenticatedClientHolder ( Some ( AllowAnyAuthenticatedClient :: new( store. clone( ) ) ) ) ;
547
+ BoxCastPtr :: to_mut_ptr( client_cert_verifier)
548
+ }
549
+ }
550
+
551
+ /// Add one or more certificate revocation lists (CRLs) to the client certificate verifier by
552
+ /// reading the CRL content from the provided buffer of PEM encoded content.
553
+ ///
554
+ /// This function may return an error if the provided buffer is not valid PEM encoded content,
555
+ /// or if the CRL content is invalid or unsupported.
556
+ #[ no_mangle]
557
+ pub extern "C" fn rustls_client_cert_verifier_builder_add_crl (
558
+ verifier : * mut rustls_client_cert_verifier_builder ,
559
+ crl_pem : * const u8 ,
560
+ crl_pem_len : size_t ,
561
+ ) -> rustls_result {
562
+ ffi_panic_boundary ! {
563
+ let client_cert_verifier_holder = match BoxCastPtr :: to_box( verifier) {
564
+ None => {
565
+ return NullParameter ;
566
+ } ,
567
+ Some ( x) => Box :: leak( x) , // nb. does not take ownership of the box.
568
+ } ;
569
+
570
+ let crl_pem: & [ u8 ] = try_slice!( crl_pem, crl_pem_len) ;
571
+ let crls_der = match crls( & mut Cursor :: new( crl_pem) ) {
572
+ Ok ( vv) => vv. into_iter( ) . map( UnparsedCertRevocationList ) . collect:: <Vec <UnparsedCertRevocationList >>( ) ,
573
+ Err ( _) => return rustls_result:: CertificateRevocationListParseError ,
574
+ } ;
575
+
576
+ let client_cert_verifier = match client_cert_verifier_holder. 0 . take( ) {
577
+ None => {
578
+ return NullParameter ;
579
+ } ,
580
+ Some ( x) => x,
581
+ } ;
582
+
583
+ match client_cert_verifier. with_crls( crls_der) {
584
+ Ok ( v) => client_cert_verifier_holder. 0 . replace( v) ,
585
+ Err ( e) => return map_error( rustls:: Error :: InvalidCertRevocationList ( e) ) ,
586
+ } ;
587
+
588
+ rustls_result:: Ok
589
+ }
590
+ }
591
+
592
+ /// Free a rustls_client_cert_verifier_builder previously returned from rustls_client_cert_verifier_builder_new.
593
+ /// Calling with NULL is fine. Must not be called twice with the same value.
594
+ #[ no_mangle]
595
+ pub extern "C" fn rustls_client_cert_verifier_builder_free (
596
+ builder : * mut rustls_client_cert_verifier_builder ,
597
+ ) {
598
+ ffi_panic_boundary ! {
599
+ let store = try_box_from_ptr!( builder) ;
600
+ drop( store)
601
+ }
602
+ }
603
+ }
604
+
512
605
/// A verifier of client certificates that requires all certificates to be
513
606
/// trusted based on a given `rustls_root_cert_store`. Usable in building server
514
607
/// configurations. Connections without such a client certificate will not
@@ -517,26 +610,37 @@ pub struct rustls_client_cert_verifier {
517
610
_private : [ u8 ; 0 ] ,
518
611
}
519
612
520
- impl CastConstPtr for rustls_client_cert_verifier {
613
+ impl CastPtr for rustls_client_cert_verifier {
521
614
type RustType = AllowAnyAuthenticatedClient ;
522
615
}
523
616
524
617
impl ArcCastPtr for rustls_client_cert_verifier { }
525
618
526
619
impl rustls_client_cert_verifier {
527
- /// Create a new client certificate verifier for the root store. The verifier
528
- /// can be used in several rustls_server_config instances. Must be freed by
620
+ /// Create a new client certificate verifier from a builder.
621
+ ///
622
+ /// The builder is consumed and is no longer valid.
623
+ ///
624
+ /// The verifier can be used in several rustls_server_config instances. Must be freed by
529
625
/// the application when no longer needed. See the documentation of
530
626
/// rustls_client_cert_verifier_free for details about lifetime.
531
- /// This copies the contents of the rustls_root_cert_store. It does not take
532
- /// ownership of the pointed-to memory.
533
627
#[ no_mangle]
534
628
pub extern "C" fn rustls_client_cert_verifier_new (
535
- store : * const rustls_root_cert_store ,
629
+ builder : * mut rustls_client_cert_verifier_builder ,
536
630
) -> * const rustls_client_cert_verifier {
537
631
ffi_panic_boundary ! {
538
- let store: & RootCertStore = try_ref_from_ptr!( store) ;
539
- let client_cert_verifier = AllowAnyAuthenticatedClient :: new( store. clone( ) ) ;
632
+ let mut client_cert_verifier_holder = match BoxCastPtr :: to_box( builder) {
633
+ None => {
634
+ return null( ) as * const _;
635
+ } ,
636
+ Some ( x) => x,
637
+ } ;
638
+ let client_cert_verifier = match client_cert_verifier_holder. 0 . take( ) {
639
+ None => {
640
+ return null( ) as * const _;
641
+ } ,
642
+ Some ( x) => x,
643
+ } ;
540
644
return Arc :: into_raw( client_cert_verifier. boxed( ) ) as * const _;
541
645
}
542
646
}
@@ -557,6 +661,101 @@ impl rustls_client_cert_verifier {
557
661
}
558
662
}
559
663
664
+ /// A builder for a `rustls_client_cert_verifier_optional`. This builder object can be used to configure
665
+ /// certificate revocation lists, and then turned into a `rustls_client_cert_verifier_optional` once ready.
666
+ pub struct rustls_client_cert_verifier_optional_builder {
667
+ _private : [ u8 ; 0 ] ,
668
+ }
669
+
670
+ // XXX: contained value is consumed even on error, so this can contain None. but the caller
671
+ // still needs to free it
672
+ pub ( crate ) struct AllowAnyAnonymousOrAuthenticatedClientHolder (
673
+ Option < AllowAnyAnonymousOrAuthenticatedClient > ,
674
+ ) ;
675
+
676
+ impl CastPtr for rustls_client_cert_verifier_optional_builder {
677
+ type RustType = AllowAnyAnonymousOrAuthenticatedClientHolder ;
678
+ }
679
+
680
+ impl BoxCastPtr for rustls_client_cert_verifier_optional_builder { }
681
+
682
+ impl rustls_client_cert_verifier_optional_builder {
683
+ /// Create a new optional client certificate verifier builder for the root store.
684
+ ///
685
+ /// This copies the contents of the rustls_root_cert_store. It does not take
686
+ /// ownership of the pointed-to memory.
687
+ ///
688
+ /// This object can then be used to load any CRLs.
689
+ ///
690
+ /// Once that is complete, convert it into a real `rustls_client_cert_verifier_optional`
691
+ /// by calling `rustls_client_cert_verifier_optional_new()`.
692
+ #[ no_mangle]
693
+ pub extern "C" fn rustls_client_cert_verifier_optional_builder_new (
694
+ store : * const rustls_root_cert_store ,
695
+ ) -> * mut rustls_client_cert_verifier_optional_builder {
696
+ ffi_panic_boundary ! {
697
+ let store: & RootCertStore = try_ref_from_ptr!( store) ;
698
+ let client_cert_verifier = AllowAnyAnonymousOrAuthenticatedClientHolder (
699
+ Some ( AllowAnyAnonymousOrAuthenticatedClient :: new( store. clone( ) ) ) ) ;
700
+ BoxCastPtr :: to_mut_ptr( client_cert_verifier)
701
+ }
702
+ }
703
+
704
+ /// Add one or more certificate revocation lists (CRLs) to the client certificate verifier by
705
+ /// reading the CRL content from the provided buffer of PEM encoded content.
706
+ ///
707
+ /// This function may return an error if the provided buffer is not valid PEM encoded content,
708
+ /// or if the CRL content is invalid or unsupported.
709
+ #[ no_mangle]
710
+ pub extern "C" fn rustls_client_cert_verifier_optional_builder_add_crl (
711
+ verifier : * mut rustls_client_cert_verifier_optional_builder ,
712
+ crl_pem : * const u8 ,
713
+ crl_pem_len : size_t ,
714
+ ) -> rustls_result {
715
+ ffi_panic_boundary ! {
716
+ let client_cert_verifier_holder = match BoxCastPtr :: to_box( verifier) {
717
+ None => {
718
+ return NullParameter ;
719
+ } ,
720
+ Some ( x) => Box :: leak( x) , // nb. does not take ownership of the box.
721
+ } ;
722
+
723
+ let crl_pem: & [ u8 ] = try_slice!( crl_pem, crl_pem_len) ;
724
+ let crls_der = match crls( & mut Cursor :: new( crl_pem) ) {
725
+ Ok ( vv) => vv. into_iter( ) . map( UnparsedCertRevocationList ) . collect:: <Vec <UnparsedCertRevocationList >>( ) ,
726
+ Err ( _) => return rustls_result:: CertificateRevocationListParseError ,
727
+ } ;
728
+
729
+ let client_cert_verifier = match client_cert_verifier_holder. 0 . take( ) {
730
+ None => {
731
+ return NullParameter ;
732
+ } ,
733
+ Some ( x) => x,
734
+ } ;
735
+
736
+ match client_cert_verifier. with_crls( crls_der) {
737
+ Ok ( v) => client_cert_verifier_holder. 0 . replace( v) ,
738
+ Err ( e) => return map_error( rustls:: Error :: InvalidCertRevocationList ( e) ) ,
739
+ } ;
740
+
741
+ rustls_result:: Ok
742
+ }
743
+ }
744
+
745
+ /// Free a rustls_client_cert_verifier_optional_builder previously returned from
746
+ /// rustls_client_cert_verifier_optional_builder_new.
747
+ /// Calling with NULL is fine. Must not be called twice with the same value.
748
+ #[ no_mangle]
749
+ pub extern "C" fn rustls_client_cert_verifier_optional_builder_free (
750
+ builder : * mut rustls_client_cert_verifier_optional_builder ,
751
+ ) {
752
+ ffi_panic_boundary ! {
753
+ let store = try_box_from_ptr!( builder) ;
754
+ drop( store)
755
+ }
756
+ }
757
+ }
758
+
560
759
/// Alternative to `rustls_client_cert_verifier` that allows connections
561
760
/// with or without a client certificate. If the client offers a certificate,
562
761
/// it will be verified (and rejected if it is not valid). If the client
@@ -575,21 +774,31 @@ impl CastConstPtr for rustls_client_cert_verifier_optional {
575
774
impl ArcCastPtr for rustls_client_cert_verifier_optional { }
576
775
577
776
impl rustls_client_cert_verifier_optional {
578
- /// Create a new rustls_client_cert_verifier_optional for the root store. The
579
- /// verifier can be used in several rustls_server_config instances. Must be
580
- /// freed by the application when no longer needed. See the documentation of
777
+ /// Create a new optional client certificate verifier from a builder.
778
+ ///
779
+ /// The builder is consumed and is no longer valid.
780
+ ///
781
+ /// The verifier can be used in several rustls_server_config instances. Must be freed by
782
+ /// the application when no longer needed. See the documentation of
581
783
/// rustls_client_cert_verifier_optional_free for details about lifetime.
582
- /// This copies the contents of the rustls_root_cert_store. It does not take
583
- /// ownership of the pointed-to data.
584
784
#[ no_mangle]
585
785
pub extern "C" fn rustls_client_cert_verifier_optional_new (
586
- store : * const rustls_root_cert_store ,
786
+ builder : * mut rustls_client_cert_verifier_optional_builder ,
587
787
) -> * const rustls_client_cert_verifier_optional {
588
788
ffi_panic_boundary ! {
589
- let store: & RootCertStore = try_ref_from_ptr!( store) ;
590
- let client_cert_verifier = AllowAnyAnonymousOrAuthenticatedClient :: new( store. clone( ) ) ;
591
- return Arc :: into_raw( client_cert_verifier. boxed( ) )
592
- as * const _;
789
+ let mut client_cert_verifier_holder = match BoxCastPtr :: to_box( builder) {
790
+ None => {
791
+ return null( ) as * const _;
792
+ } ,
793
+ Some ( x) => x,
794
+ } ;
795
+ let client_cert_verifier = match client_cert_verifier_holder. 0 . take( ) {
796
+ None => {
797
+ return null( ) as * const _;
798
+ } ,
799
+ Some ( x) => x,
800
+ } ;
801
+ return Arc :: into_raw( client_cert_verifier. boxed( ) ) as * const _;
593
802
}
594
803
}
595
804
0 commit comments