1 /*
2 * testcode/unitauth.c - unit test for authzone authoritative zone code.
3 *
4 * Copyright (c) 2017, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36 /**
37 * \file
38 * Unit test for auth zone code.
39 */
40 #include "config.h"
41 #include "services/authzone.h"
42 #include "testcode/unitmain.h"
43 #include "util/regional.h"
44 #include "util/net_help.h"
45 #include "util/config_file.h"
46 #include "util/data/msgreply.h"
47 #include "services/cache/dns.h"
48 #include "sldns/str2wire.h"
49 #include "sldns/wire2str.h"
50 #include "sldns/sbuffer.h"
51
52 /** verbosity for this test */
53 static int vbmp = 0;
54
55 /** struct for query and answer checks */
56 struct q_ans {
57 /** zone to query (delegpt) */
58 const char* zone;
59 /** query name, class, type */
60 const char* query;
61 /** additional flags or "" */
62 const char* flags;
63 /** expected answer to check against, multi-line string */
64 const char* answer;
65 };
66
67 /** auth zone for test */
68 static const char* zone_example_com =
69 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
70 "example.com. 3600 IN A 10.0.0.1\n"
71 "example.com. 3600 IN NS ns.example.com.\n"
72 "example.com. 3600 IN MX 50 mail.example.com.\n"
73 "deep.ent.example.com. 3600 IN A 10.0.0.9\n"
74 "mail.example.com. 3600 IN A 10.0.0.4\n"
75 "ns.example.com. 3600 IN A 10.0.0.5\n"
76 "out.example.com. 3600 IN CNAME www.example.com.\n"
77 "plan.example.com. 3600 IN CNAME nonexist.example.com.\n"
78 "redir.example.com. 3600 IN DNAME redir.example.org.\n"
79 "sub.example.com. 3600 IN NS ns1.sub.example.com.\n"
80 "sub.example.com. 3600 IN NS ns2.sub.example.com.\n"
81 "ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
82 "ns2.sub.example.com. 3600 IN AAAA 2001::7\n"
83 "*.wild.example.com. 3600 IN A 10.0.0.8\n"
84 "*.wild2.example.com. 3600 IN CNAME www.example.com.\n"
85 "*.wild3.example.com. 3600 IN A 10.0.0.8\n"
86 "*.wild3.example.com. 3600 IN MX 50 mail.example.com.\n"
87 "www.example.com. 3600 IN A 10.0.0.2\n"
88 "www.example.com. 3600 IN A 10.0.0.3\n"
89 "yy.example.com. 3600 IN TXT \"a\"\n"
90 "yy.example.com. 3600 IN TXT \"b\"\n"
91 "yy.example.com. 3600 IN TXT \"c\"\n"
92 "yy.example.com. 3600 IN TXT \"d\"\n"
93 "yy.example.com. 3600 IN TXT \"e\"\n"
94 "yy.example.com. 3600 IN TXT \"f\"\n"
95
96 /* and some tests for RRSIGs (rrsig is www.nlnetlabs.nl copy) */
97 /* normal: domain and 1 rrsig */
98 "z1.example.com. 3600 IN A 10.0.0.10\n"
99 "z1.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
100 /* normal: domain and 2 rrsigs */
101 "z2.example.com. 3600 IN A 10.0.0.10\n"
102 "z2.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
103 "z2.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
104 /* normal: domain and 3 rrsigs */
105 "z3.example.com. 3600 IN A 10.0.0.10\n"
106 "z3.example.com. 3600 IN A 10.0.0.11\n"
107 "z3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
108 "z3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
109 "z3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12356 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
110 /* just an RRSIG rrset with nothing else */
111 "z4.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
112 /* just an RRSIG rrset with nothing else, 2 rrsigs */
113 "z5.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
114 "z5.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
115 #if 1 /* comparison of file does not work on this part because duplicates */
116 /* are removed and the rrsets are reordered */
117 "end_of_check.z6.example.com. 3600 IN A 10.0.0.10\n"
118 /* first rrsig, then A record */
119 "z6.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
120 "z6.example.com. 3600 IN A 10.0.0.10\n"
121 /* first two rrsigs, then A record */
122 "z7.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
123 "z7.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
124 "z7.example.com. 3600 IN A 10.0.0.10\n"
125 /* first two rrsigs, then two A records */
126 "z8.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
127 "z8.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
128 "z8.example.com. 3600 IN A 10.0.0.10\n"
129 "z8.example.com. 3600 IN A 10.0.0.11\n"
130 /* duplicate RR, duplicate RRsig */
131 "z9.example.com. 3600 IN A 10.0.0.10\n"
132 "z9.example.com. 3600 IN A 10.0.0.11\n"
133 "z9.example.com. 3600 IN A 10.0.0.10\n"
134 "z9.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
135 "z9.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
136 /* different covered types, first RRSIGs then, RRs, then another RRSIG */
137 "zz10.example.com. 3600 IN RRSIG AAAA 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
138 "zz10.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
139 "zz10.example.com. 3600 IN A 10.0.0.10\n"
140 "zz10.example.com. 3600 IN RRSIG CNAME 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
141 "zz10.example.com. 3600 IN AAAA ::11\n"
142 #endif /* if0 for duplicates and reordering */
143 ;
144
145 /** queries for example.com: zone, query, flags, answer. end with NULL */
146 static struct q_ans example_com_queries[] = {
147 { "example.com", "www.example.com. A", "",
148 ";flags QR AA rcode NOERROR\n"
149 ";answer section\n"
150 "www.example.com. 3600 IN A 10.0.0.2\n"
151 "www.example.com. 3600 IN A 10.0.0.3\n"
152 },
153
154 { "example.com", "example.com. SOA", "",
155 ";flags QR AA rcode NOERROR\n"
156 ";answer section\n"
157 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
158 },
159
160 { "example.com", "example.com. A", "",
161 ";flags QR AA rcode NOERROR\n"
162 ";answer section\n"
163 "example.com. 3600 IN A 10.0.0.1\n"
164 },
165
166 { "example.com", "example.com. AAAA", "",
167 ";flags QR AA rcode NOERROR\n"
168 ";authority section\n"
169 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
170 },
171
172 { "example.com", "example.com. NS", "",
173 ";flags QR AA rcode NOERROR\n"
174 ";answer section\n"
175 "example.com. 3600 IN NS ns.example.com.\n"
176 ";additional section\n"
177 "ns.example.com. 3600 IN A 10.0.0.5\n"
178 },
179
180 { "example.com", "example.com. MX", "",
181 ";flags QR AA rcode NOERROR\n"
182 ";answer section\n"
183 "example.com. 3600 IN MX 50 mail.example.com.\n"
184 ";additional section\n"
185 "mail.example.com. 3600 IN A 10.0.0.4\n"
186 },
187
188 { "example.com", "example.com. IN ANY", "",
189 ";flags QR AA rcode NOERROR\n"
190 ";answer section\n"
191 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
192 "example.com. 3600 IN MX 50 mail.example.com.\n"
193 "example.com. 3600 IN A 10.0.0.1\n"
194 },
195
196 { "example.com", "nonexist.example.com. A", "",
197 ";flags QR AA rcode NXDOMAIN\n"
198 ";authority section\n"
199 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
200 },
201
202 { "example.com", "deep.ent.example.com. A", "",
203 ";flags QR AA rcode NOERROR\n"
204 ";answer section\n"
205 "deep.ent.example.com. 3600 IN A 10.0.0.9\n"
206 },
207
208 { "example.com", "ent.example.com. A", "",
209 ";flags QR AA rcode NOERROR\n"
210 ";authority section\n"
211 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
212 },
213
214 { "example.com", "below.deep.ent.example.com. A", "",
215 ";flags QR AA rcode NXDOMAIN\n"
216 ";authority section\n"
217 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
218 },
219
220 { "example.com", "mail.example.com. A", "",
221 ";flags QR AA rcode NOERROR\n"
222 ";answer section\n"
223 "mail.example.com. 3600 IN A 10.0.0.4\n"
224 },
225
226 { "example.com", "ns.example.com. A", "",
227 ";flags QR AA rcode NOERROR\n"
228 ";answer section\n"
229 "ns.example.com. 3600 IN A 10.0.0.5\n"
230 },
231
232 { "example.com", "out.example.com. A", "",
233 ";flags QR AA rcode NOERROR\n"
234 ";answer section\n"
235 "out.example.com. 3600 IN CNAME www.example.com.\n"
236 "www.example.com. 3600 IN A 10.0.0.2\n"
237 "www.example.com. 3600 IN A 10.0.0.3\n"
238 },
239
240 { "example.com", "out.example.com. CNAME", "",
241 ";flags QR AA rcode NOERROR\n"
242 ";answer section\n"
243 "out.example.com. 3600 IN CNAME www.example.com.\n"
244 },
245
246 { "example.com", "plan.example.com. A", "",
247 ";flags QR AA rcode NOERROR\n"
248 ";answer section\n"
249 "plan.example.com. 3600 IN CNAME nonexist.example.com.\n"
250 },
251
252 { "example.com", "plan.example.com. CNAME", "",
253 ";flags QR AA rcode NOERROR\n"
254 ";answer section\n"
255 "plan.example.com. 3600 IN CNAME nonexist.example.com.\n"
256 },
257
258 { "example.com", "redir.example.com. A", "",
259 ";flags QR AA rcode NOERROR\n"
260 ";authority section\n"
261 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
262 },
263
264 { "example.com", "redir.example.com. DNAME", "",
265 ";flags QR AA rcode NOERROR\n"
266 ";answer section\n"
267 "redir.example.com. 3600 IN DNAME redir.example.org.\n"
268 },
269
270 { "example.com", "abc.redir.example.com. A", "",
271 ";flags QR AA rcode NOERROR\n"
272 ";answer section\n"
273 "redir.example.com. 3600 IN DNAME redir.example.org.\n"
274 "abc.redir.example.com. 0 IN CNAME abc.redir.example.org.\n"
275 },
276
277 { "example.com", "foo.abc.redir.example.com. A", "",
278 ";flags QR AA rcode NOERROR\n"
279 ";answer section\n"
280 "redir.example.com. 3600 IN DNAME redir.example.org.\n"
281 "foo.abc.redir.example.com. 0 IN CNAME foo.abc.redir.example.org.\n"
282 },
283
284 { "example.com", "sub.example.com. NS", "",
285 ";flags QR rcode NOERROR\n"
286 ";authority section\n"
287 "sub.example.com. 3600 IN NS ns1.sub.example.com.\n"
288 "sub.example.com. 3600 IN NS ns2.sub.example.com.\n"
289 ";additional section\n"
290 "ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
291 "ns2.sub.example.com. 3600 IN AAAA 2001::7\n"
292 },
293
294 { "example.com", "sub.example.com. DS", "",
295 ";flags QR AA rcode NOERROR\n"
296 ";authority section\n"
297 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
298 },
299
300 { "example.com", "www.sub.example.com. NS", "",
301 ";flags QR rcode NOERROR\n"
302 ";authority section\n"
303 "sub.example.com. 3600 IN NS ns1.sub.example.com.\n"
304 "sub.example.com. 3600 IN NS ns2.sub.example.com.\n"
305 ";additional section\n"
306 "ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
307 "ns2.sub.example.com. 3600 IN AAAA 2001::7\n"
308 },
309
310 { "example.com", "foo.abc.sub.example.com. NS", "",
311 ";flags QR rcode NOERROR\n"
312 ";authority section\n"
313 "sub.example.com. 3600 IN NS ns1.sub.example.com.\n"
314 "sub.example.com. 3600 IN NS ns2.sub.example.com.\n"
315 ";additional section\n"
316 "ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
317 "ns2.sub.example.com. 3600 IN AAAA 2001::7\n"
318 },
319
320 { "example.com", "ns1.sub.example.com. A", "",
321 ";flags QR rcode NOERROR\n"
322 ";authority section\n"
323 "sub.example.com. 3600 IN NS ns1.sub.example.com.\n"
324 "sub.example.com. 3600 IN NS ns2.sub.example.com.\n"
325 ";additional section\n"
326 "ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
327 "ns2.sub.example.com. 3600 IN AAAA 2001::7\n"
328 },
329
330 { "example.com", "ns1.sub.example.com. AAAA", "",
331 ";flags QR rcode NOERROR\n"
332 ";authority section\n"
333 "sub.example.com. 3600 IN NS ns1.sub.example.com.\n"
334 "sub.example.com. 3600 IN NS ns2.sub.example.com.\n"
335 ";additional section\n"
336 "ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
337 "ns2.sub.example.com. 3600 IN AAAA 2001::7\n"
338 },
339
340 { "example.com", "ns2.sub.example.com. A", "",
341 ";flags QR rcode NOERROR\n"
342 ";authority section\n"
343 "sub.example.com. 3600 IN NS ns1.sub.example.com.\n"
344 "sub.example.com. 3600 IN NS ns2.sub.example.com.\n"
345 ";additional section\n"
346 "ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
347 "ns2.sub.example.com. 3600 IN AAAA 2001::7\n"
348 },
349
350 { "example.com", "ns2.sub.example.com. AAAA", "",
351 ";flags QR rcode NOERROR\n"
352 ";authority section\n"
353 "sub.example.com. 3600 IN NS ns1.sub.example.com.\n"
354 "sub.example.com. 3600 IN NS ns2.sub.example.com.\n"
355 ";additional section\n"
356 "ns1.sub.example.com. 3600 IN A 10.0.0.6\n"
357 "ns2.sub.example.com. 3600 IN AAAA 2001::7\n"
358 },
359
360 { "example.com", "wild.example.com. A", "",
361 ";flags QR AA rcode NOERROR\n"
362 ";authority section\n"
363 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
364 },
365
366 { "example.com", "*.wild.example.com. A", "",
367 ";flags QR AA rcode NOERROR\n"
368 ";answer section\n"
369 "*.wild.example.com. 3600 IN A 10.0.0.8\n"
370 },
371
372 { "example.com", "*.wild.example.com. AAAA", "",
373 ";flags QR AA rcode NOERROR\n"
374 ";authority section\n"
375 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
376 },
377
378 { "example.com", "abc.wild.example.com. A", "",
379 ";flags QR AA rcode NOERROR\n"
380 ";answer section\n"
381 "abc.wild.example.com. 3600 IN A 10.0.0.8\n"
382 },
383
384 { "example.com", "abc.wild.example.com. AAAA", "",
385 ";flags QR AA rcode NOERROR\n"
386 ";authority section\n"
387 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
388 },
389
390 { "example.com", "foo.abc.wild.example.com. A", "",
391 ";flags QR AA rcode NOERROR\n"
392 ";answer section\n"
393 "foo.abc.wild.example.com. 3600 IN A 10.0.0.8\n"
394 },
395
396 { "example.com", "foo.abc.wild.example.com. AAAA", "",
397 ";flags QR AA rcode NOERROR\n"
398 ";authority section\n"
399 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
400 },
401
402 { "example.com", "wild2.example.com. A", "",
403 ";flags QR AA rcode NOERROR\n"
404 ";authority section\n"
405 "example.com. 3600 IN SOA ns.example.org. noc.example.org. 2017042710 7200 3600 1209600 3600\n"
406 },
407
408 { "example.com", "*.wild2.example.com. A", "",
409 ";flags QR AA rcode NOERROR\n"
410 ";answer section\n"
411 "*.wild2.example.com. 3600 IN CNAME www.example.com.\n"
412 "www.example.com. 3600 IN A 10.0.0.2\n"
413 "www.example.com. 3600 IN A 10.0.0.3\n"
414 },
415
416 { "example.com", "abc.wild2.example.com. A", "",
417 ";flags QR AA rcode NOERROR\n"
418 ";answer section\n"
419 "abc.wild2.example.com. 3600 IN CNAME www.example.com.\n"
420 "www.example.com. 3600 IN A 10.0.0.2\n"
421 "www.example.com. 3600 IN A 10.0.0.3\n"
422 },
423
424 { "example.com", "foo.abc.wild2.example.com. A", "",
425 ";flags QR AA rcode NOERROR\n"
426 ";answer section\n"
427 "foo.abc.wild2.example.com. 3600 IN CNAME www.example.com.\n"
428 "www.example.com. 3600 IN A 10.0.0.2\n"
429 "www.example.com. 3600 IN A 10.0.0.3\n"
430 },
431
432 { "example.com", "abc.wild2.example.com. CNAME", "",
433 ";flags QR AA rcode NOERROR\n"
434 ";answer section\n"
435 "abc.wild2.example.com. 3600 IN CNAME www.example.com.\n"
436 },
437
438 { "example.com", "abc.wild3.example.com. IN ANY", "",
439 ";flags QR AA rcode NOERROR\n"
440 ";answer section\n"
441 "abc.wild3.example.com. 3600 IN MX 50 mail.example.com.\n"
442 "abc.wild3.example.com. 3600 IN A 10.0.0.8\n"
443 },
444
445 { "example.com", "yy.example.com. TXT", "",
446 ";flags QR AA rcode NOERROR\n"
447 ";answer section\n"
448 "yy.example.com. 3600 IN TXT \"a\"\n"
449 "yy.example.com. 3600 IN TXT \"b\"\n"
450 "yy.example.com. 3600 IN TXT \"c\"\n"
451 "yy.example.com. 3600 IN TXT \"d\"\n"
452 "yy.example.com. 3600 IN TXT \"e\"\n"
453 "yy.example.com. 3600 IN TXT \"f\"\n"
454 },
455
456 {NULL, NULL, NULL, NULL}
457 };
458
459 /** number of tmpfiles */
460 static int tempno = 0;
461 /** number of deleted files */
462 static int delno = 0;
463
464 /** cleanup tmp files at exit */
465 static void
tmpfilecleanup(void)466 tmpfilecleanup(void)
467 {
468 int i;
469 char buf[256];
470 for(i=0; i<tempno; i++) {
471 #ifdef USE_WINSOCK
472 snprintf(buf, sizeof(buf), "unbound.unittest.%u.%d",
473 (unsigned)getpid(), i);
474 #else
475 snprintf(buf, sizeof(buf), "/tmp/unbound.unittest.%u.%d",
476 (unsigned)getpid(), i);
477 #endif
478 if(vbmp) printf("cleanup: unlink %s\n", buf);
479 unlink(buf);
480 }
481 }
482
483 /** create temp file, return (malloced) name string, write contents to it */
484 static char*
create_tmp_file(const char * s)485 create_tmp_file(const char* s)
486 {
487 char buf[256];
488 char *fname;
489 FILE *out;
490 size_t r;
491 #ifdef USE_WINSOCK
492 snprintf(buf, sizeof(buf), "unbound.unittest.%u.%d",
493 (unsigned)getpid(), tempno++);
494 #else
495 snprintf(buf, sizeof(buf), "/tmp/unbound.unittest.%u.%d",
496 (unsigned)getpid(), tempno++);
497 #endif
498 fname = strdup(buf);
499 if(!fname) fatal_exit("out of memory");
500 /* if no string, just make the name */
501 if(!s) return fname;
502 /* if string, write to file */
503 out = fopen(fname, "w");
504 if(!out) fatal_exit("cannot open %s: %s", fname, strerror(errno));
505 r = fwrite(s, 1, strlen(s), out);
506 if(r == 0) {
507 fatal_exit("write failed: %s", strerror(errno));
508 } else if(r < strlen(s)) {
509 fatal_exit("write failed: too short (disk full?)");
510 }
511 fclose(out);
512 return fname;
513 }
514
515 /** delete temp file and free name string */
516 static void
del_tmp_file(char * fname)517 del_tmp_file(char* fname)
518 {
519 unlink(fname);
520 free(fname);
521 delno++;
522 if(delno == tempno) {
523 /* deleted all outstanding files, back to start condition */
524 tempno = 0;
525 delno = 0;
526 }
527 }
528
529 /** Add zone from file for testing */
530 struct auth_zone*
authtest_addzone(struct auth_zones * az,const char * name,char * fname)531 authtest_addzone(struct auth_zones* az, const char* name, char* fname)
532 {
533 struct auth_zone* z;
534 size_t nmlen;
535 uint8_t* nm = sldns_str2wire_dname(name, &nmlen);
536 struct config_file* cfg;
537 if(!nm) fatal_exit("out of memory");
538 lock_rw_wrlock(&az->lock);
539 z = auth_zone_create(az, nm, nmlen, LDNS_RR_CLASS_IN);
540 lock_rw_unlock(&az->lock);
541 if(!z) fatal_exit("cannot find zone");
542 auth_zone_set_zonefile(z, fname);
543 z->for_upstream = 1;
544 cfg = config_create();
545 free(cfg->chrootdir);
546 cfg->chrootdir = NULL;
547
548 if(!auth_zone_read_zonefile(z, cfg)) {
549 fatal_exit("parse failure for auth zone %s", name);
550 }
551 lock_rw_unlock(&z->lock);
552 free(nm);
553 config_delete(cfg);
554 return z;
555 }
556
557 /** check that file is the same as other file */
558 static void
checkfile(char * f1,char * f2)559 checkfile(char* f1, char *f2)
560 {
561 char buf1[10240], buf2[10240];
562 int line = 0;
563 FILE* i1, *i2;
564 i1 = fopen(f1, "r");
565 if(!i1) fatal_exit("cannot open %s: %s", f1, strerror(errno));
566 i2 = fopen(f2, "r");
567 if(!i2) fatal_exit("cannot open %s: %s", f2, strerror(errno));
568
569 while(!feof(i1) && !feof(i2)) {
570 char* cp1, *cp2;
571 line++;
572 cp1 = fgets(buf1, (int)sizeof(buf1), i1);
573 cp2 = fgets(buf2, (int)sizeof(buf2), i2);
574 if((!cp1 && !feof(i1)) || (!cp2 && !feof(i2)))
575 fatal_exit("fgets failed: %s", strerror(errno));
576 if(strncmp(buf1, "end_of_check", 12) == 0) {
577 fclose(i1);
578 fclose(i2);
579 return;
580 }
581 if(strcmp(buf1, buf2) != 0) {
582 log_info("in files %s and %s:%d", f1, f2, line);
583 log_info("'%s'", buf1);
584 log_info("'%s'", buf2);
585 fatal_exit("files are not equal");
586 }
587 }
588 unit_assert(feof(i1) && feof(i2));
589
590 fclose(i1);
591 fclose(i2);
592 }
593
594 /** check that a zone (in string) can be read and reproduced */
595 static void
check_read_exact(const char * name,const char * zone)596 check_read_exact(const char* name, const char* zone)
597 {
598 struct auth_zones* az;
599 struct auth_zone* z;
600 char* fname, *outf;
601 if(vbmp) printf("check read zone %s\n", name);
602 fname = create_tmp_file(zone);
603
604 az = auth_zones_create();
605 unit_assert(az);
606 z = authtest_addzone(az, name, fname);
607 unit_assert(z);
608 outf = create_tmp_file(NULL);
609 if(!auth_zone_write_file(z, outf)) {
610 fatal_exit("write file failed for %s", fname);
611 }
612 checkfile(fname, outf);
613
614 del_tmp_file(fname);
615 del_tmp_file(outf);
616 auth_zones_delete(az);
617 }
618
619 /** parse q_ans structure for making query */
620 static void
q_ans_parse(struct q_ans * q,struct regional * region,struct query_info ** qinfo,int * fallback,uint8_t ** dp_nm,size_t * dp_nmlen)621 q_ans_parse(struct q_ans* q, struct regional* region,
622 struct query_info** qinfo, int* fallback, uint8_t** dp_nm,
623 size_t* dp_nmlen)
624 {
625 int ret;
626 uint8_t buf[65535];
627 size_t len, dname_len;
628
629 /* parse flags */
630 *fallback = 0; /* default fallback value */
631 if(strstr(q->flags, "fallback"))
632 *fallback = 1;
633
634 /* parse zone */
635 *dp_nmlen = sizeof(buf);
636 if((ret=sldns_str2wire_dname_buf(q->zone, buf, dp_nmlen))!=0)
637 fatal_exit("cannot parse query dp zone %s : %s", q->zone,
638 sldns_get_errorstr_parse(ret));
639 *dp_nm = regional_alloc_init(region, buf, *dp_nmlen);
640 if(!dp_nm) fatal_exit("out of memory");
641
642 /* parse query */
643 len = sizeof(buf);
644 dname_len = 0;
645 if((ret=sldns_str2wire_rr_question_buf(q->query, buf, &len, &dname_len,
646 *dp_nm, *dp_nmlen, NULL, 0))!=0)
647 fatal_exit("cannot parse query %s : %s", q->query,
648 sldns_get_errorstr_parse(ret));
649 *qinfo = (struct query_info*)regional_alloc_zero(region,
650 sizeof(**qinfo));
651 if(!*qinfo) fatal_exit("out of memory");
652 (*qinfo)->qname = regional_alloc_init(region, buf, dname_len);
653 if(!(*qinfo)->qname) fatal_exit("out of memory");
654 (*qinfo)->qname_len = dname_len;
655 (*qinfo)->qtype = sldns_wirerr_get_type(buf, len, dname_len);
656 (*qinfo)->qclass = sldns_wirerr_get_class(buf, len, dname_len);
657 }
658
659 /** print flags to string */
660 static void
pr_flags(sldns_buffer * buf,uint16_t flags)661 pr_flags(sldns_buffer* buf, uint16_t flags)
662 {
663 char rcode[32];
664 sldns_buffer_printf(buf, ";flags");
665 if((flags&BIT_QR)!=0) sldns_buffer_printf(buf, " QR");
666 if((flags&BIT_AA)!=0) sldns_buffer_printf(buf, " AA");
667 if((flags&BIT_TC)!=0) sldns_buffer_printf(buf, " TC");
668 if((flags&BIT_RD)!=0) sldns_buffer_printf(buf, " RD");
669 if((flags&BIT_CD)!=0) sldns_buffer_printf(buf, " CD");
670 if((flags&BIT_RA)!=0) sldns_buffer_printf(buf, " RA");
671 if((flags&BIT_AD)!=0) sldns_buffer_printf(buf, " AD");
672 if((flags&BIT_Z)!=0) sldns_buffer_printf(buf, " Z");
673 sldns_wire2str_rcode_buf((int)(FLAGS_GET_RCODE(flags)),
674 rcode, sizeof(rcode));
675 sldns_buffer_printf(buf, " rcode %s", rcode);
676 sldns_buffer_printf(buf, "\n");
677 }
678
679 /** print RRs to string */
680 static void
pr_rrs(sldns_buffer * buf,struct reply_info * rep)681 pr_rrs(sldns_buffer* buf, struct reply_info* rep)
682 {
683 char s[65536];
684 size_t i, j;
685 struct packed_rrset_data* d;
686 log_assert(rep->rrset_count == rep->an_numrrsets + rep->ns_numrrsets
687 + rep->ar_numrrsets);
688 for(i=0; i<rep->rrset_count; i++) {
689 /* section heading */
690 if(i == 0 && rep->an_numrrsets != 0)
691 sldns_buffer_printf(buf, ";answer section\n");
692 else if(i == rep->an_numrrsets && rep->ns_numrrsets != 0)
693 sldns_buffer_printf(buf, ";authority section\n");
694 else if(i == rep->an_numrrsets+rep->ns_numrrsets &&
695 rep->ar_numrrsets != 0)
696 sldns_buffer_printf(buf, ";additional section\n");
697 /* spool RRset */
698 d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data;
699 for(j=0; j<d->count+d->rrsig_count; j++) {
700 if(!packed_rr_to_string(rep->rrsets[i], j, 0,
701 s, sizeof(s))) {
702 fatal_exit("could not rr_to_string %d",
703 (int)i);
704 }
705 sldns_buffer_printf(buf, "%s", s);
706 }
707 }
708 }
709
710 /** create string for message */
711 static char*
msgtostr(struct dns_msg * msg)712 msgtostr(struct dns_msg* msg)
713 {
714 char* str;
715 sldns_buffer* buf = sldns_buffer_new(65535);
716 if(!buf) fatal_exit("out of memory");
717 if(!msg) {
718 sldns_buffer_printf(buf, "null packet\n");
719 } else {
720 pr_flags(buf, msg->rep->flags);
721 pr_rrs(buf, msg->rep);
722 }
723
724 str = strdup((char*)sldns_buffer_begin(buf));
725 if(!str) fatal_exit("out of memory");
726 sldns_buffer_free(buf);
727 return str;
728 }
729
730 /** find line diff between strings */
731 static void
line_diff(const char * p,const char * q,const char * pdesc,const char * qdesc)732 line_diff(const char* p, const char* q, const char* pdesc, const char* qdesc)
733 {
734 char* pdup, *qdup, *pl, *ql;
735 int line = 1;
736 pdup = strdup(p);
737 qdup = strdup(q);
738 if(!pdup || !qdup) fatal_exit("out of memory");
739 pl=pdup;
740 ql=qdup;
741 printf("linediff (<%s, >%s)\n", pdesc, qdesc);
742 while(pl && ql && *pl && *ql) {
743 char* ep = strchr(pl, '\n');
744 char* eq = strchr(ql, '\n');
745 /* terminate lines */
746 if(ep) *ep = 0;
747 if(eq) *eq = 0;
748 /* printout */
749 if(strcmp(pl, ql) == 0) {
750 printf("%3d %s\n", line, pl);
751 } else {
752 printf("%3d < %s\n", line, pl);
753 printf("%3d > %s\n", line, ql);
754 }
755 if(ep) *ep = '\n';
756 if(eq) *eq = '\n';
757 if(ep) pl = ep+1;
758 else pl = NULL;
759 if(eq) ql = eq+1;
760 else ql = NULL;
761 line++;
762 }
763 if(pl && *pl) {
764 printf("%3d < %s\n", line, pl);
765 }
766 if(ql && *ql) {
767 printf("%3d > %s\n", line, ql);
768 }
769 free(pdup);
770 free(qdup);
771 }
772
773 /** make q_ans query */
774 static void
q_ans_query(struct q_ans * q,struct auth_zones * az,struct query_info * qinfo,struct regional * region,int expected_fallback,uint8_t * dp_nm,size_t dp_nmlen)775 q_ans_query(struct q_ans* q, struct auth_zones* az, struct query_info* qinfo,
776 struct regional* region, int expected_fallback, uint8_t* dp_nm,
777 size_t dp_nmlen)
778 {
779 int ret, fallback = 0;
780 struct dns_msg* msg = NULL;
781 char* ans_str;
782 int oldv = verbosity;
783 /* increase verbosity to printout logic in authzone */
784 if(vbmp) verbosity = 4;
785 ret = auth_zones_lookup(az, qinfo, region, &msg, &fallback, dp_nm,
786 dp_nmlen);
787 if(vbmp) verbosity = oldv;
788
789 /* check the answer */
790 ans_str = msgtostr(msg);
791 /* printout if vbmp */
792 if(vbmp) printf("got (ret=%s%s):\n%s",
793 (ret?"ok":"fail"), (fallback?" fallback":""), ans_str);
794 /* check expected value for ret */
795 if(expected_fallback && ret != 0) {
796 /* ret is zero on fallback */
797 if(vbmp) printf("fallback expected, but "
798 "return value is not false\n");
799 unit_assert(expected_fallback && ret == 0);
800 }
801 if(ret == 0) {
802 if(!expected_fallback) {
803 if(vbmp) printf("return value is false, "
804 "(unexpected)\n");
805 }
806 unit_assert(expected_fallback);
807 }
808 /* check expected value for fallback */
809 if(expected_fallback && !fallback) {
810 if(vbmp) printf("expected fallback, but fallback is no\n");
811 } else if(!expected_fallback && fallback) {
812 if(vbmp) printf("expected no fallback, but fallback is yes\n");
813 }
814 unit_assert( (expected_fallback&&fallback) ||
815 (!expected_fallback&&!fallback));
816 /* check answer string */
817 if(strcmp(q->answer, ans_str) != 0) {
818 if(vbmp) printf("wanted:\n%s", q->answer);
819 line_diff(q->answer, ans_str, "wanted", "got");
820 }
821 unit_assert(strcmp(q->answer, ans_str) == 0);
822 if(vbmp) printf("query ok\n\n");
823 free(ans_str);
824 }
825
826 /** check queries on a loaded zone */
827 static void
check_az_q_ans(struct auth_zones * az,struct q_ans * queries)828 check_az_q_ans(struct auth_zones* az, struct q_ans* queries)
829 {
830 struct q_ans* q;
831 struct regional* region = regional_create();
832 struct query_info* qinfo;
833 int fallback;
834 uint8_t* dp_nm;
835 size_t dp_nmlen;
836 for(q=queries; q->zone; q++) {
837 if(vbmp) printf("query %s: %s %s\n", q->zone, q->query,
838 q->flags);
839 q_ans_parse(q, region, &qinfo, &fallback, &dp_nm, &dp_nmlen);
840 q_ans_query(q, az, qinfo, region, fallback, dp_nm, dp_nmlen);
841 regional_free_all(region);
842 }
843 regional_destroy(region);
844 }
845
846 /** check queries for a zone are returned as specified */
847 static void
check_queries(const char * name,const char * zone,struct q_ans * queries)848 check_queries(const char* name, const char* zone, struct q_ans* queries)
849 {
850 struct auth_zones* az;
851 struct auth_zone* z;
852 char* fname;
853 if(vbmp) printf("check queries %s\n", name);
854 fname = create_tmp_file(zone);
855 az = auth_zones_create();
856 if(!az) fatal_exit("out of memory");
857 z = authtest_addzone(az, name, fname);
858 if(!z) fatal_exit("could not read zone for queries test");
859 del_tmp_file(fname);
860
861 /* run queries and test them */
862 check_az_q_ans(az, queries);
863
864 auth_zones_delete(az);
865 }
866
867 /** Test authzone compare_serial */
868 static void
authzone_compare_serial(void)869 authzone_compare_serial(void)
870 {
871 if(vbmp) printf("Testing compare_serial\n");
872 unit_assert(compare_serial(0, 1) < 0);
873 unit_assert(compare_serial(1, 0) > 0);
874 unit_assert(compare_serial(0, 0) == 0);
875 unit_assert(compare_serial(1, 1) == 0);
876 unit_assert(compare_serial(0xf0000000, 0xf0000000) == 0);
877 unit_assert(compare_serial(0, 0xf0000000) > 0);
878 unit_assert(compare_serial(0xf0000000, 0) < 0);
879 unit_assert(compare_serial(0xf0000000, 0xf0000001) < 0);
880 unit_assert(compare_serial(0xf0000002, 0xf0000001) > 0);
881 unit_assert(compare_serial(0x70000000, 0x80000000) < 0);
882 unit_assert(compare_serial(0x90000000, 0x70000000) > 0);
883 }
884
885 /** Test authzone read from file */
886 static void
authzone_read_test(void)887 authzone_read_test(void)
888 {
889 if(vbmp) printf("Testing read auth zone\n");
890 check_read_exact("example.com", zone_example_com);
891 }
892
893 /** Test authzone query from zone */
894 static void
authzone_query_test(void)895 authzone_query_test(void)
896 {
897 if(vbmp) printf("Testing query auth zone\n");
898 check_queries("example.com", zone_example_com, example_com_queries);
899 }
900
901 /** test authzone code */
902 void
authzone_test(void)903 authzone_test(void)
904 {
905 unit_show_feature("authzone");
906 atexit(tmpfilecleanup);
907 authzone_compare_serial();
908 authzone_read_test();
909 authzone_query_test();
910 }
911