@@ -24,7 +24,7 @@ use alloc::string::String;
24
24
/// allowed.
25
25
///
26
26
/// `DnsName` stores a copy of the input it was constructed from in a `String`
27
- /// and so it is only available when the `std ` default feature is enabled.
27
+ /// and so it is only available when the `alloc ` default feature is enabled.
28
28
///
29
29
/// `Eq`, `PartialEq`, etc. are not implemented because name comparison
30
30
/// frequently should be done case-insensitively and/or with other caveats that
@@ -147,6 +147,131 @@ impl<'a> From<DnsNameRef<'a>> for &'a str {
147
147
}
148
148
}
149
149
150
+ /// A DNS Name suitable for use in the TLS Server Name Indication (SNI)
151
+ /// extension and/or for use as the reference hostname for which to verify a
152
+ /// certificate.
153
+ pub enum GeneralDnsNameRef < ' name > {
154
+ /// a valid DNS name
155
+ DnsName ( DnsNameRef < ' name > ) ,
156
+ /// a DNS name containing a wildcard
157
+ Wildcard ( WildcardDnsNameRef < ' name > ) ,
158
+ }
159
+
160
+ impl < ' a > From < GeneralDnsNameRef < ' a > > for & ' a str {
161
+ fn from ( d : GeneralDnsNameRef < ' a > ) -> Self {
162
+ match d {
163
+ GeneralDnsNameRef :: DnsName ( name) => name. into ( ) ,
164
+ GeneralDnsNameRef :: Wildcard ( name) => name. into ( ) ,
165
+ }
166
+ }
167
+ }
168
+
169
+ /// A reference to a DNS Name suitable for use in the TLS Server Name Indication
170
+ /// (SNI) extension and/or for use as the reference hostname for which to verify
171
+ /// a certificate. Compared to `DnsName`, this one will store domain names containing
172
+ /// a wildcard.
173
+ ///
174
+ /// A `WildcardDnsName` is guaranteed to be syntactically valid. The validity rules are
175
+ /// specified in [RFC 5280 Section 7.2], except that underscores are also
176
+ /// allowed, and following [RFC 6125].
177
+ ///
178
+ /// `WildcardDnsName` stores a copy of the input it was constructed from in a `String`
179
+ /// and so it is only available when the `alloc` default feature is enabled.
180
+ ///
181
+ /// `Eq`, `PartialEq`, etc. are not implemented because name comparison
182
+ /// frequently should be done case-insensitively and/or with other caveats that
183
+ /// depend on the specific circumstances in which the comparison is done.
184
+ ///
185
+ /// [RFC 5280 Section 7.2]: https://tools.ietf.org/html/rfc5280#section-7.2
186
+ /// [RFC 6125]: https://tools.ietf.org/html/rfc6125
187
+ #[ cfg( feature = "alloc" ) ]
188
+ #[ derive( Clone , Debug , Eq , PartialEq , Hash ) ]
189
+ pub struct WildcardDnsName ( String ) ;
190
+
191
+ #[ cfg( feature = "alloc" ) ]
192
+ impl WildcardDnsName {
193
+ /// Returns a `WildcardDnsNameRef` that refers to this `WildcardDnsName`.
194
+ pub fn as_ref ( & self ) -> WildcardDnsNameRef {
195
+ WildcardDnsNameRef ( self . 0 . as_bytes ( ) )
196
+ }
197
+ }
198
+
199
+ #[ cfg( feature = "alloc" ) ]
200
+ impl AsRef < str > for WildcardDnsName {
201
+ fn as_ref ( & self ) -> & str {
202
+ self . 0 . as_ref ( )
203
+ }
204
+ }
205
+
206
+ // Deprecated
207
+ #[ cfg( feature = "alloc" ) ]
208
+ impl From < WildcardDnsNameRef < ' _ > > for WildcardDnsName {
209
+ fn from ( dns_name : WildcardDnsNameRef ) -> Self {
210
+ dns_name. to_owned ( )
211
+ }
212
+ }
213
+
214
+ /// A reference to a DNS Name suitable for use in the TLS Server Name Indication
215
+ /// (SNI) extension and/or for use as the reference hostname for which to verify
216
+ /// a certificate.
217
+ ///
218
+ /// A `WildcardDnsNameRef` is guaranteed to be syntactically valid. The validity rules
219
+ /// are specified in [RFC 5280 Section 7.2], except that underscores are also
220
+ /// allowed.
221
+ ///
222
+ /// `Eq`, `PartialEq`, etc. are not implemented because name comparison
223
+ /// frequently should be done case-insensitively and/or with other caveats that
224
+ /// depend on the specific circumstances in which the comparison is done.
225
+ ///
226
+ /// [RFC 5280 Section 7.2]: https://tools.ietf.org/html/rfc5280#section-7.2
227
+ #[ derive( Clone , Copy ) ]
228
+ pub struct WildcardDnsNameRef < ' a > ( & ' a [ u8 ] ) ;
229
+
230
+ impl < ' a > WildcardDnsNameRef < ' a > {
231
+ /// Constructs a `WildcardDnsNameRef` from the given input if the input is a
232
+ /// syntactically-valid DNS name.
233
+ pub fn try_from_ascii ( dns_name : & ' a [ u8 ] ) -> Result < Self , InvalidDnsNameError > {
234
+ if !is_valid_wildcard_dns_id ( untrusted:: Input :: from ( dns_name) ) {
235
+ return Err ( InvalidDnsNameError ) ;
236
+ }
237
+
238
+ Ok ( Self ( dns_name) )
239
+ }
240
+
241
+ /// Constructs a `WildcardDnsNameRef` from the given input if the input is a
242
+ /// syntactically-valid DNS name.
243
+ pub fn try_from_ascii_str ( dns_name : & ' a str ) -> Result < Self , InvalidDnsNameError > {
244
+ Self :: try_from_ascii ( dns_name. as_bytes ( ) )
245
+ }
246
+
247
+ /// Constructs a `WildcardDnsName` from this `WildcardDnsNameRef`
248
+ #[ cfg( feature = "alloc" ) ]
249
+ pub fn to_owned ( & self ) -> WildcardDnsName {
250
+ // WildcardDnsNameRef is already guaranteed to be valid ASCII, which is a
251
+ // subset of UTF-8.
252
+ let s: & str = self . clone ( ) . into ( ) ;
253
+ WildcardDnsName ( s. to_ascii_lowercase ( ) )
254
+ }
255
+ }
256
+
257
+ #[ cfg( feature = "alloc" ) ]
258
+ impl core:: fmt:: Debug for WildcardDnsNameRef < ' _ > {
259
+ fn fmt ( & self , f : & mut core:: fmt:: Formatter ) -> Result < ( ) , core:: fmt:: Error > {
260
+ let lowercase = self . clone ( ) . to_owned ( ) ;
261
+ f. debug_tuple ( "WildcardDnsNameRef" )
262
+ . field ( & lowercase. 0 )
263
+ . finish ( )
264
+ }
265
+ }
266
+
267
+ impl < ' a > From < WildcardDnsNameRef < ' a > > for & ' a str {
268
+ fn from ( WildcardDnsNameRef ( d) : WildcardDnsNameRef < ' a > ) -> Self {
269
+ // The unwrap won't fail because DnsNameRefs are guaranteed to be ASCII
270
+ // and ASCII is a subset of UTF-8.
271
+ core:: str:: from_utf8 ( d) . unwrap ( )
272
+ }
273
+ }
274
+
150
275
pub ( super ) fn presented_id_matches_reference_id (
151
276
presented_dns_id : untrusted:: Input ,
152
277
reference_dns_id : untrusted:: Input ,
@@ -577,6 +702,10 @@ fn is_valid_dns_id(
577
702
true
578
703
}
579
704
705
+ fn is_valid_wildcard_dns_id ( hostname : untrusted:: Input ) -> bool {
706
+ is_valid_dns_id ( hostname, IDRole :: ReferenceID , AllowWildcards :: Yes )
707
+ }
708
+
580
709
#[ cfg( test) ]
581
710
mod tests {
582
711
use super :: * ;
0 commit comments