33// This source code is licensed under the Apache License, Version 2.0 license found in the
44// LICENSE file in the root directory of this source tree.
55
6- use core:: fmt:: { self , Write } ;
6+ use core:: fmt;
77use core:: hash:: { self , Hash , Hasher } ;
88use core:: net:: IpAddr ;
99use core:: str:: Utf8Error ;
6060 dns. or_else ( || self . identifiers . first ( ) )
6161 . map ( Identifier :: value)
6262 }
63-
64- pub fn to_str_order < NewA > ( & self , alloc : NewA ) -> CertificateOrder < & str , NewA >
65- where
66- NewA : Allocator + Clone ,
67- S : AsRef < [ u8 ] > ,
68- {
69- let mut identifiers = Vec :: < Identifier < & str > , NewA > :: new_in ( alloc) ;
70- identifiers. extend ( self . identifiers . iter ( ) . map ( |x| x. as_str ( ) . unwrap ( ) ) ) ;
71-
72- CertificateOrder {
73- identifiers,
74- key : self . key . clone ( ) ,
75- }
76- }
7763}
7864
7965impl < S : Hash , A > Hash for CertificateOrder < S , A >
@@ -150,8 +136,6 @@ where
150136pub enum IdentifierError {
151137 #[ error( "memory allocation failed" ) ]
152138 Alloc ( #[ from] AllocError ) ,
153- #[ error( "empty server name" ) ]
154- Empty ,
155139 #[ error( "invalid server name" ) ]
156140 Invalid ,
157141 #[ error( "invalid UTF-8 string" ) ]
@@ -160,9 +144,9 @@ pub enum IdentifierError {
160144 Wildcard ,
161145}
162146
163- impl CertificateOrder < ngx_str_t , Pool > {
147+ impl CertificateOrder < & ' static str , Pool > {
164148 #[ inline]
165- fn push ( & mut self , id : Identifier < ngx_str_t > ) -> Result < ( ) , AllocError > {
149+ fn push ( & mut self , id : Identifier < & ' static str > ) -> Result < ( ) , AllocError > {
166150 self . identifiers . try_reserve ( 1 ) . map_err ( |_| AllocError ) ?;
167151 self . identifiers . push ( id) ;
168152 Ok ( ( ) )
@@ -190,29 +174,30 @@ impl CertificateOrder<ngx_str_t, Pool> {
190174 continue ;
191175 }
192176
193- self . try_add_identifier ( & server_name. name ) ?;
177+ // SAFETY: the value is not empty, well aligned, and the conversion result is assigned
178+ // to an object in the same pool.
179+ let value = unsafe { super :: conf_value_to_str ( & server_name. name ) ? } ;
180+
181+ self . try_add_identifier ( cf, value) ?;
194182 }
195183
196184 Ok ( ( ) )
197185 }
198186
199- pub fn try_add_identifier ( & mut self , value : & ngx_str_t ) -> Result < ( ) , IdentifierError > {
200- if value. is_empty ( ) {
201- return Err ( IdentifierError :: Empty ) ;
202- }
203-
204- if core:: str:: from_utf8 ( value. as_ref ( ) ) ?
205- . parse :: < IpAddr > ( )
206- . is_ok ( )
207- {
208- return self . push ( Identifier :: Ip ( * value) ) . map_err ( Into :: into) ;
187+ pub fn try_add_identifier (
188+ & mut self ,
189+ cf : & ngx_conf_t ,
190+ value : & ' static str ,
191+ ) -> Result < ( ) , IdentifierError > {
192+ if value. parse :: < IpAddr > ( ) . is_ok ( ) {
193+ return self . push ( Identifier :: Ip ( value) ) . map_err ( Into :: into) ;
209194 }
210195
211- if value. as_bytes ( ) . contains ( & b '*') {
196+ if value. contains ( '*' ) {
212197 return Err ( IdentifierError :: Wildcard ) ;
213198 }
214199
215- let host = validate_host ( self . identifiers . allocator ( ) , * value) . map_err ( |st| {
200+ let host = validate_host ( cf , value) . map_err ( |st| {
216201 if st == Status :: NGX_ERROR {
217202 IdentifierError :: Alloc ( AllocError )
218203 } else {
@@ -226,18 +211,14 @@ impl CertificateOrder<ngx_str_t, Pool> {
226211 * See <https://nginx.org/en/docs/http/server_names.html>
227212 */
228213
229- if let Some ( host) = host. strip_prefix ( b ".") {
230- let mut www = NgxString :: new_in ( self . identifiers . allocator ( ) ) ;
231- www. try_reserve_exact ( host. len + 4 )
214+ if let Some ( host) = host. strip_prefix ( "." ) {
215+ let mut www = Vec :: new_in ( self . identifiers . allocator ( ) . clone ( ) ) ;
216+ www. try_reserve_exact ( host. len ( ) + 4 )
232217 . map_err ( |_| AllocError ) ?;
233- // write to a buffer of sufficient size will succeed
234- let _ = write ! ( & mut www, "www.{host}" ) ;
235-
236- let parts = www. into_raw_parts ( ) ;
237- let www = ngx_str_t {
238- data : parts. 0 ,
239- len : parts. 1 ,
240- } ;
218+ www. extend_from_slice ( b"www." ) ;
219+ www. extend_from_slice ( host. as_bytes ( ) ) ;
220+ // The buffer is owned by ngx_pool_t and does not leak.
221+ let www = core:: str:: from_utf8 ( www. leak ( ) ) ?;
241222
242223 self . push ( Identifier :: Dns ( www) ) ?;
243224 self . push ( Identifier :: Dns ( host) ) ?;
@@ -273,11 +254,17 @@ where
273254 }
274255}
275256
276- fn validate_host ( pool : & Pool , mut host : ngx_str_t ) -> Result < ngx_str_t , Status > {
277- let mut pool = pool. clone ( ) ;
278- let rc = Status ( unsafe { nginx_sys:: ngx_http_validate_host ( & mut host, pool. as_mut ( ) , 1 ) } ) ;
257+ /// Checks if the value is a valid domain name and returns a canonical (lowercase) form,
258+ /// reallocated on the configuration pool if necessary.
259+ fn validate_host ( cf : & ngx_conf_t , host : & ' static str ) -> Result < & ' static str , Status > {
260+ let mut host = ngx_str_t {
261+ data : host. as_ptr ( ) . cast_mut ( ) ,
262+ len : host. len ( ) ,
263+ } ;
264+ let rc = Status ( unsafe { nginx_sys:: ngx_http_validate_host ( & mut host, cf. pool , 0 ) } ) ;
279265 if rc != Status :: NGX_OK {
280266 return Err ( rc) ;
281267 }
282- Ok ( host)
268+
269+ unsafe { super :: conf_value_to_str ( & host) } . map_err ( |_| Status :: NGX_ERROR )
283270}
0 commit comments