1 /* MIT License
2 *
3 * Copyright (c) The c-ares project and its contributors
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * SPDX-License-Identifier: MIT
25 */
26 #include "ares-test.h"
27 #include "dns-proto.h"
28
29 #include <sstream>
30 #include <vector>
31
32 namespace ares {
33 namespace test {
34
TEST_F(LibraryTest,ParseAReplyOK)35 TEST_F(LibraryTest, ParseAReplyOK) {
36 DNSPacket pkt;
37 pkt.set_qid(0x1234).set_response().set_aa()
38 .add_question(new DNSQuestion("example.com", T_A))
39 .add_answer(new DNSARR("example.com", 0x01020304, {2,3,4,5}))
40 .add_answer(new DNSAaaaRR("example.com", 0x01020304, {0,0,0,0,0,0,0,0,0,0,0,0,2,3,4,5}));
41 std::vector<byte> data = {
42 0x12, 0x34, // qid
43 0x84, // response + query + AA + not-TC + not-RD
44 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
45 0x00, 0x01, // num questions
46 0x00, 0x02, // num answer RRs
47 0x00, 0x00, // num authority RRs
48 0x00, 0x00, // num additional RRs
49 // Question
50 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
51 0x03, 'c', 'o', 'm',
52 0x00,
53 0x00, 0x01, // type A
54 0x00, 0x01, // class IN
55 // Answer 1
56 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
57 0x03, 'c', 'o', 'm',
58 0x00,
59 0x00, 0x01, // RR type
60 0x00, 0x01, // class IN
61 0x01, 0x02, 0x03, 0x04, // TTL
62 0x00, 0x04, // rdata length
63 0x02, 0x03, 0x04, 0x05,
64 // Answer 2
65 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
66 0x03, 'c', 'o', 'm',
67 0x00,
68 0x00, 0x1c, // RR type
69 0x00, 0x01, // class IN
70 0x01, 0x02, 0x03, 0x04, // TTL
71 0x00, 0x10, // rdata length
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x04, 0x05,
73 };
74 EXPECT_EQ(data, pkt.data());
75 struct hostent *host = nullptr;
76 struct ares_addrttl info[5];
77 int count = 5;
78 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), (int)data.size(),
79 &host, info, &count));
80 EXPECT_EQ(1, count);
81 EXPECT_EQ(0x01020304, info[0].ttl);
82 unsigned long expected_addr = htonl(0x02030405);
83 EXPECT_EQ(expected_addr, info[0].ipaddr.s_addr);
84 EXPECT_EQ("2.3.4.5", AddressToString(&(info[0].ipaddr), 4));
85 ASSERT_NE(nullptr, host);
86 std::stringstream ss;
87 ss << HostEnt(host);
88 EXPECT_EQ("{'example.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
89 ares_free_hostent(host);
90
91 // Repeat without providing a hostent
92 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), (int)data.size(),
93 nullptr, info, &count));
94 EXPECT_EQ(1, count);
95 EXPECT_EQ(0x01020304, info[0].ttl);
96 EXPECT_EQ(expected_addr, info[0].ipaddr.s_addr);
97 EXPECT_EQ("2.3.4.5", AddressToString(&(info[0].ipaddr), 4));
98 }
99
TEST_F(LibraryTest,ParseMalformedAReply)100 TEST_F(LibraryTest, ParseMalformedAReply) {
101 std::vector<byte> data = {
102 0x12, 0x34, // [0:2) qid
103 0x84, // [2] response + query + AA + not-TC + not-RD
104 0x00, // [3] not-RA + not-Z + not-AD + not-CD + rc=NoError
105 0x00, 0x01, // [4:6) num questions
106 0x00, 0x02, // [6:8) num answer RRs
107 0x00, 0x00, // [8:10) num authority RRs
108 0x00, 0x00, // [10:12) num additional RRs
109 // Question
110 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', // [12:20)
111 0x03, 'c', 'o', 'm', // [20,24)
112 0x00, // [24]
113 0x00, 0x01, // [25:26) type A
114 0x00, 0x01, // [27:29) class IN
115 // Answer 1
116 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', // [29:37)
117 0x03, 'c', 'o', 'm', // [37:41)
118 0x00, // [41]
119 0x00, 0x01, // [42:44) RR type
120 0x00, 0x01, // [44:46) class IN
121 0x01, 0x02, 0x03, 0x04, // [46:50) TTL
122 0x00, 0x04, // [50:52) rdata length
123 0x02, 0x03, 0x04, 0x05, // [52,56)
124 };
125 struct hostent *host = nullptr;
126 struct ares_addrttl info[2];
127 int count = 2;
128
129 // Invalid RR-len.
130 std::vector<byte> invalid_rrlen(data);
131 invalid_rrlen[51] = 180;
132 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(invalid_rrlen.data(), (int)invalid_rrlen.size(),
133 &host, info, &count));
134
135 // Truncate mid-question.
136 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), 26,
137 &host, info, &count));
138
139 // Truncate mid-answer.
140 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), 42,
141 &host, info, &count));
142
143 // Negative length
144 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), -1,
145 &host, info, &count));
146 }
147
TEST_F(LibraryTest,ParseAReplyNoData)148 TEST_F(LibraryTest, ParseAReplyNoData) {
149 DNSPacket pkt;
150 pkt.set_qid(0x1234).set_response().set_aa()
151 .add_question(new DNSQuestion("example.com", T_A));
152 std::vector<byte> data = pkt.data();
153 struct hostent *host = nullptr;
154 struct ares_addrttl info[2];
155 int count = 2;
156 EXPECT_EQ(ARES_ENODATA, ares_parse_a_reply(data.data(), (int)data.size(),
157 &host, info, &count));
158 EXPECT_EQ(0, count);
159 EXPECT_EQ(nullptr, host);
160
161 // Again but with a CNAME.
162 pkt.add_answer(new DNSCnameRR("example.com", 200, "c.example.com"));
163 data = pkt.data();
164 // Expect success as per https://github.com/c-ares/c-ares/commit/2c63440127feed70ccefb148b8f938a2df6c15f8
165 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), (int)data.size(),
166 &host, info, &count));
167 EXPECT_EQ(0, count);
168 EXPECT_NE(nullptr, host);
169 std::stringstream ss;
170 ss << HostEnt(host);
171 EXPECT_EQ("{'c.example.com' aliases=[example.com] addrs=[]}", ss.str());
172 ares_free_hostent(host);
173 }
174
TEST_F(LibraryTest,ParseAReplyVariantA)175 TEST_F(LibraryTest, ParseAReplyVariantA) {
176 DNSPacket pkt;
177 pkt.set_qid(6366).set_rd().set_ra()
178 .add_question(new DNSQuestion("mit.edu", T_A))
179 .add_answer(new DNSARR("mit.edu", 52, {18,7,22,69}))
180 .add_auth(new DNSNsRR("mit.edu", 292, "W20NS.mit.edu"))
181 .add_auth(new DNSNsRR("mit.edu", 292, "BITSY.mit.edu"))
182 .add_auth(new DNSNsRR("mit.edu", 292, "STRAWB.mit.edu"))
183 .add_additional(new DNSARR("STRAWB.mit.edu", 292, {18,71,0,151}));
184 struct hostent *host = nullptr;
185 struct ares_addrttl info[2];
186 int count = 2;
187 std::vector<byte> data = pkt.data();
188 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), (int)data.size(),
189 &host, info, &count));
190 EXPECT_EQ(1, count);
191 EXPECT_EQ("18.7.22.69", AddressToString(&(info[0].ipaddr), 4));
192 EXPECT_EQ(52, info[0].ttl);
193 ares_free_hostent(host);
194 }
195
TEST_F(LibraryTest,ParseAReplyJustCname)196 TEST_F(LibraryTest, ParseAReplyJustCname) {
197 DNSPacket pkt;
198 pkt.set_qid(6366).set_rd().set_ra()
199 .add_question(new DNSQuestion("mit.edu", T_A))
200 .add_answer(new DNSCnameRR("mit.edu", 52, "other.mit.edu"));
201 struct hostent *host = nullptr;
202 struct ares_addrttl info[2];
203 int count = 2;
204 std::vector<byte> data = pkt.data();
205 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), (int)data.size(),
206 &host, info, &count));
207 EXPECT_EQ(0, count);
208 ASSERT_NE(nullptr, host);
209 std::stringstream ss;
210 ss << HostEnt(host);
211 EXPECT_EQ("{'other.mit.edu' aliases=[mit.edu] addrs=[]}", ss.str());
212 ares_free_hostent(host);
213 }
214
TEST_F(LibraryTest,ParseAReplyVariantCname)215 TEST_F(LibraryTest, ParseAReplyVariantCname) {
216 DNSPacket pkt;
217 pkt.set_qid(6366).set_rd().set_ra()
218 .add_question(new DNSQuestion("query.example.com", T_A))
219 .add_answer(new DNSCnameRR("query.example.com", 200, "redirect.query.example.com"))
220 .add_answer(new DNSARR("redirect.query.example.com", 300, {129,97,123,22}))
221 .add_auth(new DNSNsRR("example.com", 218, "aa.ns1.example.com"))
222 .add_auth(new DNSNsRR("example.com", 218, "ns2.example.com"))
223 .add_auth(new DNSNsRR("example.com", 218, "ns3.example.com"))
224 .add_auth(new DNSNsRR("example.com", 218, "ns4.example.com"))
225 .add_additional(new DNSARR("aa.ns1.example.com", 218, {129,97,1,1}))
226 .add_additional(new DNSARR("ns2.example.com", 218, {129,97,1,2}))
227 .add_additional(new DNSARR("ns3.example.com", 218, {129,97,1,3}))
228 .add_additional(new DNSARR("ns4.example.com", 218, {129,97,1,4}));
229 struct hostent *host = nullptr;
230 struct ares_addrttl info[2];
231 int count = 2;
232 std::vector<byte> data = pkt.data();
233 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), (int)data.size(),
234 &host, info, &count));
235 EXPECT_EQ(1, count);
236 EXPECT_EQ("129.97.123.22", AddressToString(&(info[0].ipaddr), 4));
237 // TTL is reduced to match CNAME's.
238 EXPECT_EQ(200, info[0].ttl);
239 ares_free_hostent(host);
240
241 // Repeat parsing without places to put the results.
242 count = 0;
243 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), (int)data.size(),
244 nullptr, info, &count));
245 }
246
TEST_F(LibraryTest,ParseAReplyVariantCnameChain)247 TEST_F(LibraryTest, ParseAReplyVariantCnameChain) {
248 DNSPacket pkt;
249 pkt.set_qid(6366).set_rd().set_ra()
250 .add_question(new DNSQuestion("c1.localhost", T_A))
251 .add_answer(new DNSCnameRR("c1.localhost", 604800, "c2.localhost"))
252 .add_answer(new DNSCnameRR("c2.localhost", 604800, "c3.localhost"))
253 .add_answer(new DNSCnameRR("c3.localhost", 604800, "c4.localhost"))
254 .add_answer(new DNSARR("c4.localhost", 604800, {8,8,8,8}))
255 .add_auth(new DNSNsRR("localhost", 604800, "localhost"))
256 .add_additional(new DNSARR("localhost", 604800, {127,0,0,1}))
257 .add_additional(new DNSAaaaRR("localhost", 604800,
258 {0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}));
260 struct hostent *host = nullptr;
261 struct ares_addrttl info[2];
262 int count = 2;
263 std::vector<byte> data = pkt.data();
264 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), (int)data.size(),
265 &host, info, &count));
266 EXPECT_EQ(1, count);
267 EXPECT_EQ("8.8.8.8", AddressToString(&(info[0].ipaddr), 4));
268 EXPECT_EQ(604800, info[0].ttl);
269 ares_free_hostent(host);
270 }
271
TEST_F(LibraryTest,ParseAReplyErrors)272 TEST_F(LibraryTest, ParseAReplyErrors) {
273 DNSPacket pkt;
274 pkt.set_qid(0x1234).set_response().set_aa()
275 .add_question(new DNSQuestion("example.com", T_A))
276 .add_answer(new DNSARR("example.com", 100, {0x02, 0x03, 0x04, 0x05}));
277 std::vector<byte> data;
278
279 struct hostent *host = nullptr;
280 struct ares_addrttl info[2];
281 int count = 2;
282
283 // No question.
284 pkt.questions_.clear();
285 data = pkt.data();
286 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), (int)data.size(),
287 &host, info, &count));
288 EXPECT_EQ(nullptr, host);
289 pkt.add_question(new DNSQuestion("example.com", T_A));
290
291 // Question != answer, this is ok as of Issue #683
292 pkt.questions_.clear();
293 pkt.add_question(new DNSQuestion("Axample.com", T_A));
294 data = pkt.data();
295 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), (int)data.size(),
296 &host, info, &count));
297 ASSERT_NE(nullptr, host);
298 std::stringstream ss;
299 ss << HostEnt(host);
300 EXPECT_EQ("{'axample.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
301 ares_free_hostent(host);
302 host = nullptr;
303
304 pkt.questions_.clear();
305 pkt.add_question(new DNSQuestion("example.com", T_A));
306
307 #ifdef DISABLED
308 // Not a response.
309 pkt.set_response(false);
310 data = pkt.data();
311 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), (int)data.size(),
312 &host, info, &count));
313 EXPECT_EQ(nullptr, host);
314 pkt.set_response(true);
315
316 // Bad return code.
317 pkt.set_rcode(FORMERR);
318 data = pkt.data();
319 EXPECT_EQ(ARES_ENODATA, ares_parse_a_reply(data.data(), (int)data.size(),
320 &host, info, &count));
321 EXPECT_EQ(nullptr, host);
322 pkt.set_rcode(NOERROR);
323 #endif
324
325 // Two questions
326 pkt.add_question(new DNSQuestion("example.com", T_A));
327 data = pkt.data();
328 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), (int)data.size(),
329 &host, info, &count));
330 EXPECT_EQ(nullptr, host);
331 pkt.questions_.clear();
332 pkt.add_question(new DNSQuestion("example.com", T_A));
333
334 // Wrong sort of answer.
335 pkt.answers_.clear();
336 pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com"));
337 data = pkt.data();
338 EXPECT_EQ(ARES_ENODATA, ares_parse_a_reply(data.data(), (int)data.size(),
339 &host, info, &count));
340 EXPECT_EQ(nullptr, host);
341 pkt.answers_.clear();
342 pkt.add_answer(new DNSARR("example.com", 100, {0x02, 0x03, 0x04, 0x05}));
343
344 // No answer.
345 pkt.answers_.clear();
346 data = pkt.data();
347 EXPECT_EQ(ARES_ENODATA, ares_parse_a_reply(data.data(), (int)data.size(),
348 &host, info, &count));
349 EXPECT_EQ(nullptr, host);
350 pkt.add_answer(new DNSARR("example.com", 100, {0x02, 0x03, 0x04, 0x05}));
351
352 // Truncated packets.
353 data = pkt.data();
354 for (size_t len = 1; len < data.size(); len++) {
355 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), (int)len,
356 &host, info, &count));
357 EXPECT_EQ(nullptr, host);
358 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), (int)len,
359 nullptr, info, &count));
360 }
361 }
362
TEST_F(LibraryTest,ParseAReplyAllocFail)363 TEST_F(LibraryTest, ParseAReplyAllocFail) {
364 DNSPacket pkt;
365 pkt.set_qid(0x1234).set_response().set_aa()
366 .add_question(new DNSQuestion("example.com", T_A))
367 .add_answer(new DNSCnameRR("example.com", 300, "c.example.com"))
368 .add_answer(new DNSARR("c.example.com", 500, {0x02, 0x03, 0x04, 0x05}));
369 std::vector<byte> data = pkt.data();
370
371 struct hostent *host = nullptr;
372 struct ares_addrttl info[2];
373 int count = 2;
374
375 for (int ii = 1; ii <= 8; ii++) {
376 ClearFails();
377 SetAllocFail(ii);
378 EXPECT_EQ(ARES_ENOMEM, ares_parse_a_reply(data.data(), (int)data.size(),
379 &host, info, &count)) << ii;
380 EXPECT_EQ(nullptr, host);
381 }
382 }
383
384 } // namespace test
385 } // namespace ares
386