3030#define MAX_INDIRS 50
3131
3232static int name_length (const unsigned char * encoded , const unsigned char * abuf ,
33- int alen );
33+ int alen , int is_hostname );
3434
3535/* Reserved characters for names that need to be escaped */
3636static int is_reservedch (int ch )
@@ -52,6 +52,31 @@ static int is_reservedch(int ch)
5252 return 0 ;
5353}
5454
55+ static int ares__isprint (int ch )
56+ {
57+ if (ch >= 0x20 && ch <= 0x7E )
58+ return 1 ;
59+ return 0 ;
60+ }
61+
62+ /* Character set allowed by hostnames */
63+ static int is_hostnamech (int ch )
64+ {
65+ /* [A-Za-z0-9-.]
66+ * Don't use isalnum() as it is locale-specific
67+ */
68+ if (ch >= 'A' && ch <= 'Z' )
69+ return 1 ;
70+ if (ch >= 'a' && ch <= 'z' )
71+ return 1 ;
72+ if (ch >= '0' && ch <= '9' )
73+ return 1 ;
74+ if (ch == '-' || ch == '.' )
75+ return 1 ;
76+
77+ return 0 ;
78+ }
79+
5580/* Expand an RFC1035-encoded domain name given by encoded. The
5681 * containing message is given by abuf and alen. The result given by
5782 * *s, which is set to a NUL-terminated allocated buffer. *enclen is
@@ -74,10 +99,15 @@ static int is_reservedch(int ch)
7499 *
75100 * Since the expanded name uses '.' as a label separator, we use
76101 * backslashes to escape periods or backslashes in the expanded name.
102+ *
103+ * If the result is expected to be a hostname, then no escaped data is allowed
104+ * and will return error.
77105 */
78106
79- int ares_expand_name (const unsigned char * encoded , const unsigned char * abuf ,
80- int alen , char * * s , long * enclen )
107+ int ares__expand_name_validated (const unsigned char * encoded ,
108+ const unsigned char * abuf ,
109+ int alen , char * * s , long * enclen ,
110+ int is_hostname )
81111{
82112 int len , indir = 0 ;
83113 char * q ;
@@ -87,7 +117,7 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
87117 size_t uns ;
88118 } nlen ;
89119
90- nlen .sig = name_length (encoded , abuf , alen );
120+ nlen .sig = name_length (encoded , abuf , alen , is_hostname );
91121 if (nlen .sig < 0 )
92122 return ARES_EBADNAME ;
93123
@@ -135,9 +165,8 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
135165 {
136166 /* Output as \DDD for consistency with RFC1035 5.1, except
137167 * for the special case of a root name response */
138- if (!isprint (* p ) && !(name_len == 1 && * p == 0 ))
168+ if (!ares__isprint (* p ) && !(name_len == 1 && * p == 0 ))
139169 {
140-
141170 * q ++ = '\\' ;
142171 * q ++ = '0' + * p / 100 ;
143172 * q ++ = '0' + (* p % 100 ) / 10 ;
@@ -170,11 +199,18 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
170199 return ARES_SUCCESS ;
171200}
172201
202+
203+ int ares_expand_name (const unsigned char * encoded , const unsigned char * abuf ,
204+ int alen , char * * s , long * enclen )
205+ {
206+ return ares__expand_name_validated (encoded , abuf , alen , s , enclen , 0 );
207+ }
208+
173209/* Return the length of the expansion of an encoded domain name, or
174210 * -1 if the encoding is invalid.
175211 */
176212static int name_length (const unsigned char * encoded , const unsigned char * abuf ,
177- int alen )
213+ int alen , int is_hostname )
178214{
179215 int n = 0 , offset , indir = 0 , top ;
180216
@@ -212,16 +248,22 @@ static int name_length(const unsigned char *encoded, const unsigned char *abuf,
212248
213249 while (offset -- )
214250 {
215- if (!isprint (* encoded ) && !(name_len == 1 && * encoded == 0 ))
251+ if (!ares__isprint (* encoded ) && !(name_len == 1 && * encoded == 0 ))
216252 {
253+ if (is_hostname )
254+ return -1 ;
217255 n += 4 ;
218256 }
219257 else if (is_reservedch (* encoded ))
220258 {
259+ if (is_hostname )
260+ return -1 ;
221261 n += 2 ;
222262 }
223263 else
224264 {
265+ if (is_hostname && !is_hostnamech (* encoded ))
266+ return -1 ;
225267 n += 1 ;
226268 }
227269 encoded ++ ;
@@ -244,12 +286,14 @@ static int name_length(const unsigned char *encoded, const unsigned char *abuf,
244286 return (n ) ? n - 1 : n ;
245287}
246288
247- /* Like ares_expand_name but returns EBADRESP in case of invalid input. */
289+ /* Like ares_expand_name_validated but returns EBADRESP in case of invalid
290+ * input. */
248291int ares__expand_name_for_response (const unsigned char * encoded ,
249292 const unsigned char * abuf , int alen ,
250- char * * s , long * enclen )
293+ char * * s , long * enclen , int is_hostname )
251294{
252- int status = ares_expand_name (encoded , abuf , alen , s , enclen );
295+ int status = ares__expand_name_validated (encoded , abuf , alen , s , enclen ,
296+ is_hostname );
253297 if (status == ARES_EBADNAME )
254298 status = ARES_EBADRESP ;
255299 return status ;
0 commit comments