]>
Commit | Line | Data |
---|---|---|
446997ff | 1 | /* Test the behavior of the trust-ad option. |
d614a753 | 2 | Copyright (C) 2019-2020 Free Software Foundation, Inc. |
446997ff FW |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
17 | <https://www.gnu.org/licenses/>. */ | |
18 | ||
19 | #include <resolv.h> | |
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
22 | #include <support/check.h> | |
23 | #include <support/check_nss.h> | |
24 | #include <support/resolv_test.h> | |
25 | #include <support/support.h> | |
26 | ||
27 | /* This controls properties of the response. volatile because | |
28 | __res_send is incorrectly declared as __THROW. */ | |
29 | static volatile unsigned char response_number; | |
30 | static volatile bool response_ad_bit; | |
31 | static volatile bool query_ad_bit; | |
32 | ||
33 | static void | |
34 | response (const struct resolv_response_context *ctx, | |
35 | struct resolv_response_builder *b, | |
36 | const char *qname, uint16_t qclass, uint16_t qtype) | |
37 | { | |
38 | TEST_COMPARE (qclass, C_IN); | |
39 | TEST_COMPARE (qtype, T_A); | |
40 | TEST_COMPARE_STRING (qname, "www.example"); | |
41 | ||
42 | HEADER header; | |
43 | memcpy (&header, ctx->query_buffer, sizeof (header)); | |
44 | TEST_COMPARE (header.ad, query_ad_bit); | |
45 | ||
46 | struct resolv_response_flags flags = { .ad = response_ad_bit, }; | |
47 | resolv_response_init (b, flags); | |
48 | resolv_response_add_question (b, qname, qclass, qtype); | |
49 | resolv_response_section (b, ns_s_an); | |
50 | resolv_response_open_record (b, qname, qclass, T_A, 0x12345678); | |
51 | char addr[4] = { 192, 0, 2, response_number }; | |
52 | resolv_response_add_data (b, addr, sizeof (addr)); | |
53 | resolv_response_close_record (b); | |
54 | } | |
55 | ||
56 | static void | |
57 | check_answer (const unsigned char *buffer, size_t buffer_length, | |
58 | bool expected_ad) | |
59 | { | |
60 | HEADER header; | |
61 | TEST_VERIFY (buffer_length > sizeof (header)); | |
62 | memcpy (&header, buffer, sizeof (header)); | |
63 | TEST_COMPARE (0, header.aa); | |
64 | TEST_COMPARE (expected_ad, header.ad); | |
65 | TEST_COMPARE (0, header.opcode); | |
66 | TEST_COMPARE (1, header.qr); | |
67 | TEST_COMPARE (0, header.rcode); | |
68 | TEST_COMPARE (1, header.rd); | |
69 | TEST_COMPARE (0, header.tc); | |
70 | TEST_COMPARE (1, ntohs (header.qdcount)); | |
71 | TEST_COMPARE (1, ntohs (header.ancount)); | |
72 | TEST_COMPARE (0, ntohs (header.nscount)); | |
73 | TEST_COMPARE (0, ntohs (header.arcount)); | |
74 | ||
75 | char *description = xasprintf ("response=%d ad=%d", | |
76 | response_number, expected_ad); | |
77 | char *expected = xasprintf ("name: www.example\n" | |
78 | "address: 192.0.2.%d\n", response_number); | |
79 | check_dns_packet (description, buffer, buffer_length, expected); | |
80 | free (expected); | |
81 | free (description); | |
82 | } | |
83 | ||
84 | static int | |
85 | do_test (void) | |
86 | { | |
87 | struct resolv_test *aux = resolv_test_start | |
88 | ((struct resolv_redirect_config) | |
89 | { | |
90 | .response_callback = response, | |
91 | }); | |
92 | ||
93 | /* By default, the resolver is not trusted, and the AD bit is | |
94 | cleared. */ | |
95 | ||
96 | static const unsigned char hand_crafted_query[] = | |
97 | { | |
98 | 10, 11, /* Transaction ID. */ | |
99 | 1, 0x20, /* Query with RD, AD flags. */ | |
100 | 0, 1, /* One question. */ | |
101 | 0, 0, 0, 0, 0, 0, /* The other sections are empty. */ | |
102 | 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0, | |
103 | 0, T_A, /* A query. */ | |
104 | 0, 1, /* Class IN. */ | |
105 | }; | |
106 | ||
107 | ++response_number; | |
108 | response_ad_bit = false; | |
109 | ||
110 | unsigned char buffer[512]; | |
111 | memset (buffer, 255, sizeof (buffer)); | |
112 | query_ad_bit = true; | |
113 | int ret = res_send (hand_crafted_query, sizeof (hand_crafted_query), | |
114 | buffer, sizeof (buffer)); | |
115 | TEST_VERIFY (ret > 0); | |
116 | check_answer (buffer, ret, false); | |
117 | ||
118 | ++response_number; | |
119 | memset (buffer, 255, sizeof (buffer)); | |
120 | query_ad_bit = false; | |
121 | ret = res_query ("www.example", C_IN, T_A, buffer, sizeof (buffer)); | |
122 | TEST_VERIFY (ret > 0); | |
123 | check_answer (buffer, ret, false); | |
124 | response_ad_bit = true; | |
125 | ||
126 | response_ad_bit = true; | |
127 | ||
128 | ++response_number; | |
129 | query_ad_bit = true; | |
130 | ret = res_send (hand_crafted_query, sizeof (hand_crafted_query), | |
131 | buffer, sizeof (buffer)); | |
132 | TEST_VERIFY (ret > 0); | |
133 | check_answer (buffer, ret, false); | |
134 | ||
135 | ++response_number; | |
136 | memset (buffer, 255, sizeof (buffer)); | |
137 | query_ad_bit = false; | |
138 | ret = res_query ("www.example", C_IN, T_A, buffer, sizeof (buffer)); | |
139 | TEST_VERIFY (ret > 0); | |
140 | check_answer (buffer, ret, false); | |
141 | ||
142 | /* No AD bit set in generated queries. */ | |
143 | memset (buffer, 255, sizeof (buffer)); | |
144 | ret = res_mkquery (QUERY, "www.example", C_IN, T_A, | |
145 | (const unsigned char *) "", 0, NULL, | |
146 | buffer, sizeof (buffer)); | |
147 | HEADER header; | |
148 | memcpy (&header, buffer, sizeof (header)); | |
149 | TEST_VERIFY (!header.ad); | |
150 | ||
151 | /* With RES_TRUSTAD, the AD bit is passed through if it set in the | |
152 | response. It is also included in queries. */ | |
153 | ||
154 | _res.options |= RES_TRUSTAD; | |
155 | query_ad_bit = true; | |
156 | ||
157 | response_ad_bit = false; | |
158 | ||
159 | ++response_number; | |
160 | memset (buffer, 255, sizeof (buffer)); | |
161 | ret = res_send (hand_crafted_query, sizeof (hand_crafted_query), | |
162 | buffer, sizeof (buffer)); | |
163 | TEST_VERIFY (ret > 0); | |
164 | check_answer (buffer, ret, false); | |
165 | ||
166 | ++response_number; | |
167 | memset (buffer, 255, sizeof (buffer)); | |
168 | ret = res_query ("www.example", C_IN, T_A, buffer, sizeof (buffer)); | |
169 | TEST_VERIFY (ret > 0); | |
170 | check_answer (buffer, ret, false); | |
171 | ||
172 | response_ad_bit = true; | |
173 | ||
174 | ++response_number; | |
175 | memset (buffer, 0, sizeof (buffer)); | |
176 | ret = res_send (hand_crafted_query, sizeof (hand_crafted_query), | |
177 | buffer, sizeof (buffer)); | |
178 | TEST_VERIFY (ret > 0); | |
179 | check_answer (buffer, ret, true); | |
180 | ||
181 | ++response_number; | |
182 | memset (buffer, 0, sizeof (buffer)); | |
183 | ret = res_query ("www.example", C_IN, T_A, buffer, sizeof (buffer)); | |
184 | TEST_VERIFY (ret > 0); | |
185 | check_answer (buffer, ret, true); | |
186 | ||
187 | /* AD bit set in generated queries. */ | |
188 | memset (buffer, 0, sizeof (buffer)); | |
189 | ret = res_mkquery (QUERY, "www.example", C_IN, T_A, | |
190 | (const unsigned char *) "", 0, NULL, | |
191 | buffer, sizeof (buffer)); | |
192 | memcpy (&header, buffer, sizeof (header)); | |
193 | TEST_VERIFY (header.ad); | |
194 | ||
195 | resolv_test_end (aux); | |
196 | ||
197 | return 0; | |
198 | } | |
199 | ||
200 | #include <support/test-driver.c> |