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