@@ -10,7 +10,7 @@ use crate::{
10
10
Certificate , CertificateParams , Error , Issuer , PublicKeyData , SignatureAlgorithm , SigningKey ,
11
11
} ;
12
12
#[ cfg( feature = "x509-parser" ) ]
13
- use crate :: { DistinguishedName , SanType } ;
13
+ use crate :: { CustomExtension , DistinguishedName , SanType } ;
14
14
15
15
/// A public key, extracted from a CSR
16
16
#[ derive( Debug , PartialEq , Eq , Hash ) ]
@@ -65,6 +65,18 @@ impl From<CertificateSigningRequest> for CertificateSigningRequestDer<'static> {
65
65
}
66
66
}
67
67
68
+ /// A unsupported extension.
69
+ #[ derive( Debug , Clone , Eq , PartialEq ) ]
70
+ #[ cfg( feature = "x509-parser" ) ]
71
+ pub struct UnsupportedExtension < ' a > {
72
+ /// The Object ID of the extension.
73
+ pub oid : Vec < u64 > ,
74
+ /// The unparsed value.
75
+ pub value : & ' a [ u8 ] ,
76
+ /// Whether the extension is critical.
77
+ pub critical : bool ,
78
+ }
79
+
68
80
/// Parameters for a certificate signing request
69
81
#[ derive( Debug ) ]
70
82
pub struct CertificateSigningRequestParams {
@@ -84,6 +96,23 @@ impl CertificateSigningRequestParams {
84
96
Self :: from_der ( & csr. contents ( ) . into ( ) )
85
97
}
86
98
99
+ /// Parse a certificate signing request from the ASCII PEM format
100
+ /// using the provided validator function to handle unknown extension
101
+ /// types.
102
+ ///
103
+ /// The validator function must return an error if the attribute OID or value
104
+ /// is incorrect.
105
+ ///
106
+ /// See [`from_der`](Self::from_der) for more details.
107
+ #[ cfg( all( feature = "pem" , feature = "x509-parser" ) ) ]
108
+ pub fn from_pem_custom_validator < F > ( pem_str : & str , valid_fn : F ) -> Result < Self , Error >
109
+ where
110
+ F : FnMut ( & UnsupportedExtension < ' _ > ) -> Result < ( ) , Error > ,
111
+ {
112
+ let csr = pem:: parse ( pem_str) . or ( Err ( Error :: CouldNotParseCertificationRequest ) ) ?;
113
+ Self :: from_der_custom_validator ( & csr. contents ( ) . into ( ) , valid_fn)
114
+ }
115
+
87
116
/// Parse a certificate signing request from DER-encoded bytes
88
117
///
89
118
/// Currently, this only supports the `Subject Alternative Name` extension.
@@ -96,6 +125,24 @@ impl CertificateSigningRequestParams {
96
125
/// [`rustls_pemfile::csr()`]: https://docs.rs/rustls-pemfile/latest/rustls_pemfile/fn.csr.html
97
126
#[ cfg( feature = "x509-parser" ) ]
98
127
pub fn from_der ( csr : & CertificateSigningRequestDer < ' _ > ) -> Result < Self , Error > {
128
+ Self :: from_der_custom_validator ( csr, |_| Ok ( ( ) ) )
129
+ }
130
+
131
+ /// Parse a certificate signing request from DER-encoded bytes using the provided
132
+ /// validator function to handle unknown extension types.
133
+ ///
134
+ /// The validator function must return an error if the attribute OID or value
135
+ /// is incorrect.
136
+ ///
137
+ /// See [`from_der`](Self::from_der) for more details.
138
+ #[ cfg( feature = "x509-parser" ) ]
139
+ pub fn from_der_custom_validator < F > (
140
+ csr : & CertificateSigningRequestDer < ' _ > ,
141
+ mut valid_fn : F ,
142
+ ) -> Result < Self , Error >
143
+ where
144
+ F : FnMut ( & UnsupportedExtension < ' _ > ) -> Result < ( ) , Error > ,
145
+ {
99
146
use crate :: KeyUsagePurpose ;
100
147
use x509_parser:: prelude:: FromDer ;
101
148
@@ -171,7 +218,25 @@ impl CertificateSigningRequestParams {
171
218
return Err ( Error :: UnsupportedExtension ) ;
172
219
}
173
220
} ,
174
- _ => return Err ( Error :: UnsupportedExtension ) ,
221
+ x509_parser:: extensions:: ParsedExtension :: UnsupportedExtension ( val) => {
222
+ let oid: Vec < u64 > = match val. oid . iter ( ) {
223
+ Some ( iter) => iter. collect ( ) ,
224
+ None => return Err ( Error :: UnsupportedExtension ) ,
225
+ } ;
226
+ let ext = UnsupportedExtension {
227
+ oid,
228
+ value : val. value ,
229
+ critical : val. critical ,
230
+ } ;
231
+ valid_fn ( & ext) ?;
232
+ let mut ext =
233
+ CustomExtension :: from_oid_content ( & ext. oid , val. value . to_vec ( ) ) ;
234
+ ext. set_criticality ( val. critical ) ;
235
+ params. custom_extensions . push ( ext) ;
236
+ } ,
237
+ _ => {
238
+ return Err ( Error :: UnsupportedExtension ) ;
239
+ } ,
175
240
}
176
241
}
177
242
}
0 commit comments