@@ -18,19 +18,20 @@ use ngx::async_::sleep;
1818use ngx:: collections:: Vec ;
1919use ngx:: ngx_log_debug;
2020use openssl:: pkey:: { PKey , PKeyRef , Private } ;
21- use openssl:: x509:: { self , extension as x509_ext, X509Req } ;
21+ use openssl:: x509:: { self , extension as x509_ext, X509Req , X509 } ;
2222use types:: { AccountStatus , ProblemCategory } ;
2323
2424use self :: account_key:: { AccountKey , AccountKeyError } ;
2525use self :: types:: { AuthorizationStatus , ChallengeKind , ChallengeStatus , OrderStatus } ;
2626use crate :: conf:: identifier:: Identifier ;
27- use crate :: conf:: issuer:: { Issuer , Profile } ;
27+ use crate :: conf:: issuer:: { CertificateChainMatcher , Issuer , Profile } ;
2828use crate :: conf:: order:: CertificateOrder ;
2929use crate :: net:: http:: HttpClient ;
3030use crate :: time:: Time ;
3131
3232pub mod account_key;
3333pub mod error;
34+ pub mod headers;
3435pub mod solvers;
3536pub mod types;
3637
@@ -53,7 +54,8 @@ pub enum NewAccountOutput<'a> {
5354}
5455
5556pub struct NewCertificateOutput {
56- pub chain : Bytes ,
57+ pub bytes : Bytes ,
58+ pub x509 : std:: vec:: Vec < X509 > ,
5759 pub pkey : PKey < Private > ,
5860}
5961
@@ -272,7 +274,7 @@ where
272274 if let Some ( val) = res
273275 . headers ( )
274276 . get ( http:: header:: RETRY_AFTER )
275- . and_then ( parse_retry_after)
277+ . and_then ( headers :: parse_retry_after)
276278 . filter ( |x| x > & MAX_SERVER_RETRY_INTERVAL )
277279 {
278280 return Err ( RequestError :: RateLimited ( val) ) ;
@@ -487,11 +489,69 @@ where
487489
488490 let certificate = order
489491 . certificate
490- . ok_or ( NewCertificateError :: CertificateUrl ) ?;
492+ . ok_or ( NewCertificateError :: MissingCertificate ) ?;
491493
492- let chain = self . post ( & certificate, b"" ) . await ?. into_body ( ) ;
494+ let res = self . post ( & certificate, b"" ) . await ?;
493495
494- Ok ( NewCertificateOutput { chain, pkey } )
496+ if let Some ( ref matcher) = self . issuer . chain {
497+ let ( bytes, x509) = self
498+ . find_preferred_chain ( & certificate, res, matcher)
499+ . await ?;
500+ Ok ( NewCertificateOutput { bytes, x509, pkey } )
501+ } else {
502+ let bytes = res. into_body ( ) ;
503+ let x509 =
504+ X509 :: stack_from_pem ( & bytes) . map_err ( NewCertificateError :: InvalidCertificate ) ?;
505+ if x509. is_empty ( ) {
506+ return Err ( NewCertificateError :: MissingCertificate ) ;
507+ }
508+
509+ Ok ( NewCertificateOutput { bytes, x509, pkey } )
510+ }
511+ }
512+
513+ async fn find_preferred_chain (
514+ & self ,
515+ base : & Uri ,
516+ cert : http:: Response < Bytes > ,
517+ matcher : & CertificateChainMatcher ,
518+ ) -> Result < ( Bytes , std:: vec:: Vec < X509 > ) , NewCertificateError > {
519+ let default =
520+ X509 :: stack_from_pem ( cert. body ( ) ) . map_err ( NewCertificateError :: InvalidCertificate ) ?;
521+
522+ if !matcher. test ( & default) {
523+ if let Ok ( base) = iri_string:: types:: UriAbsoluteString :: try_from ( base. to_string ( ) ) {
524+ let alternates = cert
525+ . headers ( )
526+ . get_all ( http:: header:: LINK )
527+ . into_iter ( )
528+ . filter_map ( headers:: parse_link)
529+ . flatten ( )
530+ . filter ( |x| x. is_rel ( "alternate" ) ) ;
531+
532+ for link in alternates {
533+ let uri = link. target . resolve_against ( & base) . to_string ( ) ;
534+ let Ok ( uri) = Uri :: try_from ( uri) else {
535+ continue ;
536+ } ;
537+
538+ let res = self . post ( & uri, b"" ) . await ?;
539+ let bytes = res. into_body ( ) ;
540+
541+ let stack = X509 :: stack_from_pem ( & bytes)
542+ . map_err ( NewCertificateError :: InvalidCertificate ) ?;
543+ if matcher. test ( & stack) {
544+ return Ok ( ( bytes, stack) ) ;
545+ }
546+ }
547+ }
548+ }
549+
550+ if default. is_empty ( ) {
551+ return Err ( NewCertificateError :: MissingCertificate ) ;
552+ }
553+
554+ Ok ( ( cert. into_body ( ) , default) )
495555 }
496556
497557 async fn do_authorization (
@@ -612,7 +672,7 @@ async fn wait_for_retry<B>(
612672 let retry_after = res
613673 . headers ( )
614674 . get ( http:: header:: RETRY_AFTER )
615- . and_then ( parse_retry_after)
675+ . and_then ( headers :: parse_retry_after)
616676 . unwrap_or ( interval)
617677 . min ( MAX_SERVER_RETRY_INTERVAL ) ;
618678
@@ -642,15 +702,3 @@ where
642702{
643703 serde_json:: from_slice ( bytes) . map_err ( RequestError :: ResponseFormat )
644704}
645-
646- fn parse_retry_after ( val : & http:: HeaderValue ) -> Option < Duration > {
647- let val = val. to_str ( ) . ok ( ) ?;
648-
649- // Retry-After: <http-date>
650- if let Ok ( time) = Time :: parse ( val) {
651- return Some ( time - Time :: now ( ) ) ;
652- }
653-
654- // Retry-After: <delay-seconds>
655- val. parse ( ) . map ( Duration :: from_secs) . ok ( )
656- }
0 commit comments