• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,ParseTxtReplyOK)35 TEST_F(LibraryTest, ParseTxtReplyOK) {
36   DNSPacket pkt;
37   std::string expected1 = "txt1.example.com";
38   std::string expected2a = "txt2a";
39   std::string expected2b("ABC\0ABC", 7);
40   pkt.set_qid(0x1234).set_response().set_aa()
41     .add_question(new DNSQuestion("example.com", T_TXT))
42     .add_answer(new DNSTxtRR("example.com", 100, {expected1}))
43     .add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b}));
44   std::vector<byte> data = pkt.data();
45 
46   struct ares_txt_reply* txt = nullptr;
47   EXPECT_EQ(ARES_SUCCESS, ares_parse_txt_reply(data.data(), (int)data.size(), &txt));
48   ASSERT_NE(nullptr, txt);
49   EXPECT_EQ(std::vector<byte>(expected1.data(), expected1.data() + expected1.size()),
50             std::vector<byte>(txt->txt, txt->txt + txt->length));
51 
52   struct ares_txt_reply* txt2 = txt->next;
53   ASSERT_NE(nullptr, txt2);
54   EXPECT_EQ(std::vector<byte>(expected2a.data(), expected2a.data() + expected2a.size()),
55             std::vector<byte>(txt2->txt, txt2->txt + txt2->length));
56 
57   struct ares_txt_reply* txt3 = txt2->next;
58   ASSERT_NE(nullptr, txt3);
59   EXPECT_EQ(std::vector<byte>(expected2b.data(), expected2b.data() + expected2b.size()),
60             std::vector<byte>(txt3->txt, txt3->txt + txt3->length));
61   EXPECT_EQ(nullptr, txt3->next);
62   ares_free_data(txt);
63 }
64 
TEST_F(LibraryTest,ParseTxtExtReplyOK)65 TEST_F(LibraryTest, ParseTxtExtReplyOK) {
66   DNSPacket pkt;
67   std::string expected1 = "txt1.example.com";
68   std::string expected2a = "txt2a";
69   std::string expected2b("ABC\0ABC", 7);
70   pkt.set_qid(0x1234).set_response().set_aa()
71     .add_question(new DNSQuestion("example.com", T_TXT))
72     .add_answer(new DNSTxtRR("example.com", 100, {expected1}))
73     .add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b}));
74   std::vector<byte> data = pkt.data();
75 
76   struct ares_txt_ext* txt = nullptr;
77   EXPECT_EQ(ARES_SUCCESS, ares_parse_txt_reply_ext(data.data(), (int)data.size(), &txt));
78   ASSERT_NE(nullptr, txt);
79   EXPECT_EQ(std::vector<byte>(expected1.data(), expected1.data() + expected1.size()),
80             std::vector<byte>(txt->txt, txt->txt + txt->length));
81   EXPECT_EQ(1, txt->record_start);
82 
83   struct ares_txt_ext* txt2 = txt->next;
84   ASSERT_NE(nullptr, txt2);
85   EXPECT_EQ(std::vector<byte>(expected2a.data(), expected2a.data() + expected2a.size()),
86             std::vector<byte>(txt2->txt, txt2->txt + txt2->length));
87   EXPECT_EQ(1, txt2->record_start);
88 
89   struct ares_txt_ext* txt3 = txt2->next;
90   ASSERT_NE(nullptr, txt3);
91   EXPECT_EQ(std::vector<byte>(expected2b.data(), expected2b.data() + expected2b.size()),
92             std::vector<byte>(txt3->txt, txt3->txt + txt3->length));
93   EXPECT_EQ(nullptr, txt3->next);
94   EXPECT_EQ(0, txt3->record_start);
95   ares_free_data(txt);
96 }
97 
TEST_F(LibraryTest,ParseTxtEmpty)98 TEST_F(LibraryTest, ParseTxtEmpty) {
99   DNSPacket pkt;
100   std::string expected1 = "";
101   pkt.set_qid(0x1234).set_response().set_aa()
102     .add_question(new DNSQuestion("example.com", T_TXT))
103     .add_answer(new DNSTxtRR("example.com", 100, {expected1}));
104   std::vector<byte> data = pkt.data();
105 
106   ares_dns_record_t   *dnsrec = NULL;
107   ares_dns_rr_t       *rr     = NULL;
108   EXPECT_EQ(ARES_SUCCESS, ares_dns_parse(data.data(), data.size(), 0, &dnsrec));
109   EXPECT_EQ(1, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER));
110   rr = ares_dns_record_rr_get(dnsrec, ARES_SECTION_ANSWER, 0);
111   ASSERT_NE(nullptr, rr);
112   EXPECT_EQ(ARES_REC_TYPE_TXT, ares_dns_rr_get_type(rr));
113 
114   size_t txtdata_len;
115   const unsigned char *txtdata;
116 
117   /* Using array methodology */
118   EXPECT_EQ(1, ares_dns_rr_get_abin_cnt(rr, ARES_RR_TXT_DATA));
119   txtdata = ares_dns_rr_get_abin(rr, ARES_RR_TXT_DATA, 0, &txtdata_len);
120   EXPECT_EQ(txtdata_len, 0);
121   EXPECT_NE(nullptr, txtdata);
122 
123   /* Using combined methodology */
124   txtdata = ares_dns_rr_get_bin(rr, ARES_RR_TXT_DATA, &txtdata_len);
125   EXPECT_EQ(txtdata_len, 0);
126   EXPECT_NE(nullptr, txtdata);
127 
128   ares_dns_record_destroy(dnsrec); dnsrec = NULL;
129 }
130 
TEST_F(LibraryTest,ParseTxtMalformedReply1)131 TEST_F(LibraryTest, ParseTxtMalformedReply1) {
132   std::vector<byte> data = {
133     0x12, 0x34,  // qid
134     0x84, // response + query + AA + not-TC + not-RD
135     0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
136     0x00, 0x01,  // num questions
137     0x00, 0x01,  // num answer RRs
138     0x00, 0x00,  // num authority RRs
139     0x00, 0x00,  // num additional RRs
140     // Question
141     0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
142     0x03, 'c', 'o', 'm',
143     0x00,
144     0x00, 0x10,  // type TXT
145     0x00, 0x01,  // class IN
146     // Answer 1
147     0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
148     0x03, 'c', 'o', 'm',
149     0x00,
150     0x00, 0x10,  // RR type
151     0x00, 0x01,  // class IN
152     0x01, 0x02, 0x03, 0x04, // TTL
153     0x00, 0x03,  // rdata length
154     0x12, 'a', 'b',  // invalid length
155   };
156 
157   struct ares_txt_reply* txt = nullptr;
158   EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), (int)data.size(), &txt));
159   ASSERT_EQ(nullptr, txt);
160 }
161 
TEST_F(LibraryTest,ParseTxtMalformedReply2)162 TEST_F(LibraryTest, ParseTxtMalformedReply2) {
163   std::vector<byte> data = {
164     0x12, 0x34,  // qid
165     0x84, // response + query + AA + not-TC + not-RD
166     0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
167     0x00, 0x01,  // num questions
168     0x00, 0x01,  // num answer RRs
169     0x00, 0x00,  // num authority RRs
170     0x00, 0x00,  // num additional RRs
171     // Question
172     0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
173     0x03, 'c', 'o', 'm',
174     0x00,
175     0x00, 0x10,  // type TXT
176     0x00, 0x01,  // class IN
177     // Answer 1
178     0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
179     0x03, 'c', 'o', 'm',
180     0x00,
181     0x00, 0x10,  // RR type
182     // truncated
183   };
184 
185   struct ares_txt_reply* txt = nullptr;
186   EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), (int)data.size(), &txt));
187   ASSERT_EQ(nullptr, txt);
188 }
189 
TEST_F(LibraryTest,ParseTxtMalformedReply3)190 TEST_F(LibraryTest, ParseTxtMalformedReply3) {
191   std::vector<byte> data = {
192     0x12, 0x34,  // qid
193     0x84, // response + query + AA + not-TC + not-RD
194     0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
195     0x00, 0x01,  // num questions
196     0x00, 0x01,  // num answer RRs
197     0x00, 0x00,  // num authority RRs
198     0x00, 0x00,  // num additional RRs
199     // Question
200     0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
201     0x03, 'c', 'o', 'm',
202     0x00,
203     0x00, 0x10,  // type TXT
204     0x00, 0x01,  // class IN
205     // Answer 1
206     0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
207     0x03, 'c', 'o', 'm',
208     0x00,
209     0x00, 0x10,  // RR type
210     0x00, 0x01,  // class IN
211     0x01, 0x02, 0x03, 0x04, // TTL
212     0x00, 0x13,  // rdata length INVALID
213     0x02, 'a', 'b',
214   };
215 
216   struct ares_txt_reply* txt = nullptr;
217   EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), (int)data.size(), &txt));
218   ASSERT_EQ(nullptr, txt);
219 }
220 
TEST_F(LibraryTest,ParseTxtMalformedReply4)221 TEST_F(LibraryTest, ParseTxtMalformedReply4) {
222   std::vector<byte> data = {
223     0x12, 0x34,  // qid
224     0x84, // response + query + AA + not-TC + not-RD
225     0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
226     0x00, 0x01,  // num questions
227     0x00, 0x01,  // num answer RRs
228     0x00, 0x00,  // num authority RRs
229     0x00, 0x00,  // num additional RRs
230     // Question
231     0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
232     0x03, 'c', 'o', 'm',
233     0x00,
234     0x00, 0x10,  // type TXT
235     0x00, // TRUNCATED
236   };
237 
238   struct ares_txt_reply* txt = nullptr;
239   EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), (int)data.size(), &txt));
240   ASSERT_EQ(nullptr, txt);
241 }
242 
TEST_F(LibraryTest,ParseTxtReplyErrors)243 TEST_F(LibraryTest, ParseTxtReplyErrors) {
244   DNSPacket pkt;
245   std::string expected1 = "txt1.example.com";
246   std::string expected2a = "txt2a";
247   std::string expected2b = "txt2b";
248   pkt.set_qid(0x1234).set_response().set_aa()
249     .add_question(new DNSQuestion("example.com", T_TXT))
250     .add_answer(new DNSTxtRR("example.com", 100, {expected1}))
251     .add_answer(new DNSTxtRR("example.com", 100, {expected1}))
252     .add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b}));
253   std::vector<byte> data = pkt.data();
254   struct ares_txt_reply* txt = nullptr;
255   struct ares_txt_ext* txt_ext = nullptr;
256 
257   // No question.
258   pkt.questions_.clear();
259   data = pkt.data();
260   txt = nullptr;
261   EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), (int)data.size(), &txt));
262   EXPECT_EQ(nullptr, txt);
263   pkt.add_question(new DNSQuestion("example.com", T_TXT));
264 
265 #ifdef DISABLED
266   // Question != answer
267   pkt.questions_.clear();
268   pkt.add_question(new DNSQuestion("Axample.com", T_TXT));
269   data = pkt.data();
270   EXPECT_EQ(ARES_ENODATA, ares_parse_txt_reply(data.data(), (int)data.size(), &txt));
271   pkt.questions_.clear();
272   pkt.add_question(new DNSQuestion("example.com", T_TXT));
273 #endif
274 
275   // Two questions.
276   pkt.add_question(new DNSQuestion("example.com", T_TXT));
277   data = pkt.data();
278   txt = nullptr;
279   EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), (int)data.size(), &txt));
280   EXPECT_EQ(nullptr, txt);
281   pkt.questions_.clear();
282   pkt.add_question(new DNSQuestion("example.com", T_TXT));
283 
284   // No answer.
285   pkt.answers_.clear();
286   data = pkt.data();
287   txt = nullptr;
288   EXPECT_EQ(ARES_ENODATA, ares_parse_txt_reply(data.data(), (int)data.size(), &txt));
289   EXPECT_EQ(nullptr, txt);
290   pkt.add_answer(new DNSTxtRR("example.com", 100, {expected1}));
291 
292   // Truncated packets.
293   for (size_t len = 1; len < data.size(); len++) {
294     txt = nullptr;
295     EXPECT_NE(ARES_SUCCESS, ares_parse_txt_reply(data.data(), (int)len, &txt));
296     EXPECT_EQ(nullptr, txt);
297   }
298 
299   // Negative Length
300   EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), -1, &txt));
301   EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply_ext(data.data(), -1, &txt_ext));
302 }
303 
TEST_F(LibraryTest,ParseTxtReplyAllocFail)304 TEST_F(LibraryTest, ParseTxtReplyAllocFail) {
305   DNSPacket pkt;
306   std::string expected1 = "txt1.example.com";
307   std::string expected2a = "txt2a";
308   std::string expected2b = "txt2b";
309   pkt.set_qid(0x1234).set_response().set_aa()
310     .add_question(new DNSQuestion("example.com", T_TXT))
311     .add_answer(new DNSCnameRR("example.com", 300, "c.example.com"))
312     .add_answer(new DNSTxtRR("c.example.com", 100, {expected1}))
313     .add_answer(new DNSTxtRR("c.example.com", 100, {expected1}))
314     .add_answer(new DNSTxtRR("c.example.com", 100, {expected2a, expected2b}));
315   std::vector<byte> data = pkt.data();
316   struct ares_txt_reply* txt = nullptr;
317 
318   for (int ii = 1; ii <= 13; ii++) {
319     ClearFails();
320     SetAllocFail(ii);
321     EXPECT_EQ(ARES_ENOMEM, ares_parse_txt_reply(data.data(), (int)data.size(), &txt)) << ii;
322   }
323 }
324 
325 
326 }  // namespace test
327 }  // namespace ares
328