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
466 tmpfilecleanup(void)
467 {
468 	int i;
469 	char buf[256];
470 	for(i=0; i<tempno; i++) {
471 		snprintf(buf, sizeof(buf), "/tmp/unbound.unittest.%u.%d",
472 			(unsigned)getpid(), i);
473 		if(vbmp) printf("cleanup: unlink %s\n", buf);
474 		unlink(buf);
475 	}
476 }
477 
478 /** create temp file, return (malloced) name string, write contents to it */
479 static char*
480 create_tmp_file(const char* s)
481 {
482 	char buf[256];
483 	char *fname;
484 	FILE *out;
485 	size_t r;
486 	snprintf(buf, sizeof(buf), "/tmp/unbound.unittest.%u.%d",
487 		(unsigned)getpid(), tempno++);
488 	fname = strdup(buf);
489 	if(!fname) fatal_exit("out of memory");
490 	/* if no string, just make the name */
491 	if(!s) return fname;
492 	/* if string, write to file */
493 	out = fopen(fname, "w");
494 	if(!out) fatal_exit("cannot open %s: %s", fname, strerror(errno));
495 	r = fwrite(s, 1, strlen(s), out);
496 	if(r == 0) {
497 		fatal_exit("write failed: %s", strerror(errno));
498 	} else if(r < strlen(s)) {
499 		fatal_exit("write failed: too short (disk full?)");
500 	}
501 	fclose(out);
502 	return fname;
503 }
504 
505 /** delete temp file and free name string */
506 static void
507 del_tmp_file(char* fname)
508 {
509 	unlink(fname);
510 	free(fname);
511 	delno++;
512 	if(delno == tempno) {
513 		/* deleted all outstanding files, back to start condition */
514 		tempno = 0;
515 		delno = 0;
516 	}
517 }
518 
519 /** Add zone from file for testing */
520 static struct auth_zone*
521 addzone(struct auth_zones* az, const char* name, char* fname)
522 {
523 	struct auth_zone* z;
524 	size_t nmlen;
525 	uint8_t* nm = sldns_str2wire_dname(name, &nmlen);
526 	struct config_file* cfg;
527 	if(!nm) fatal_exit("out of memory");
528 	lock_rw_wrlock(&az->lock);
529 	z = auth_zone_create(az, nm, nmlen, LDNS_RR_CLASS_IN);
530 	lock_rw_unlock(&az->lock);
531 	if(!z) fatal_exit("cannot find zone");
532 	auth_zone_set_zonefile(z, fname);
533 	z->for_upstream = 1;
534 	cfg = config_create();
535 	free(cfg->chrootdir);
536 	cfg->chrootdir = NULL;
537 
538 	if(!auth_zone_read_zonefile(z, cfg)) {
539 		fatal_exit("parse failure for auth zone %s", name);
540 	}
541 	lock_rw_unlock(&z->lock);
542 	free(nm);
543 	config_delete(cfg);
544 	return z;
545 }
546 
547 /** check that file is the same as other file */
548 static void
549 checkfile(char* f1, char *f2)
550 {
551 	char buf1[10240], buf2[10240];
552 	int line = 0;
553 	FILE* i1, *i2;
554 	i1 = fopen(f1, "r");
555 	if(!i1) fatal_exit("cannot open %s: %s", f1, strerror(errno));
556 	i2 = fopen(f2, "r");
557 	if(!i2) fatal_exit("cannot open %s: %s", f2, strerror(errno));
558 
559 	while(!feof(i1) && !feof(i2)) {
560 		char* cp1, *cp2;
561 		line++;
562 		cp1 = fgets(buf1, (int)sizeof(buf1), i1);
563 		cp2 = fgets(buf2, (int)sizeof(buf2), i2);
564 		if((!cp1 && !feof(i1)) || (!cp2 && !feof(i2)))
565 			fatal_exit("fgets failed: %s", strerror(errno));
566 		if(strncmp(buf1, "end_of_check", 12) == 0) {
567 			fclose(i1);
568 			fclose(i2);
569 			return;
570 		}
571 		if(strcmp(buf1, buf2) != 0) {
572 			log_info("in files %s and %s:%d", f1, f2, line);
573 			log_info("'%s'", buf1);
574 			log_info("'%s'", buf2);
575 			fatal_exit("files are not equal");
576 		}
577 	}
578 	unit_assert(feof(i1) && feof(i2));
579 
580 	fclose(i1);
581 	fclose(i2);
582 }
583 
584 /** check that a zone (in string) can be read and reproduced */
585 static void
586 check_read_exact(const char* name, const char* zone)
587 {
588 	struct auth_zones* az;
589 	struct auth_zone* z;
590 	char* fname, *outf;
591 	if(vbmp) printf("check read zone %s\n", name);
592 	fname = create_tmp_file(zone);
593 
594 	az = auth_zones_create();
595 	unit_assert(az);
596 	z = addzone(az, name, fname);
597 	unit_assert(z);
598 	outf = create_tmp_file(NULL);
599 	if(!auth_zone_write_file(z, outf)) {
600 		fatal_exit("write file failed for %s", fname);
601 	}
602 	checkfile(fname, outf);
603 
604 	del_tmp_file(fname);
605 	del_tmp_file(outf);
606 	auth_zones_delete(az);
607 }
608 
609 /** parse q_ans structure for making query */
610 static void
611 q_ans_parse(struct q_ans* q, struct regional* region,
612 	struct query_info** qinfo, int* fallback, uint8_t** dp_nm,
613 	size_t* dp_nmlen)
614 {
615 	int ret;
616 	uint8_t buf[65535];
617 	size_t len, dname_len;
618 
619 	/* parse flags */
620 	*fallback = 0; /* default fallback value */
621 	if(strstr(q->flags, "fallback"))
622 		*fallback = 1;
623 
624 	/* parse zone */
625 	*dp_nmlen = sizeof(buf);
626 	if((ret=sldns_str2wire_dname_buf(q->zone, buf, dp_nmlen))!=0)
627 		fatal_exit("cannot parse query dp zone %s : %s", q->zone,
628 			sldns_get_errorstr_parse(ret));
629 	*dp_nm = regional_alloc_init(region, buf, *dp_nmlen);
630 	if(!dp_nm) fatal_exit("out of memory");
631 
632 	/* parse query */
633 	len = sizeof(buf);
634 	dname_len = 0;
635 	if((ret=sldns_str2wire_rr_question_buf(q->query, buf, &len, &dname_len,
636 		*dp_nm, *dp_nmlen, NULL, 0))!=0)
637 		fatal_exit("cannot parse query %s : %s", q->query,
638 			sldns_get_errorstr_parse(ret));
639 	*qinfo = (struct query_info*)regional_alloc_zero(region,
640 		sizeof(**qinfo));
641 	if(!*qinfo) fatal_exit("out of memory");
642 	(*qinfo)->qname = regional_alloc_init(region, buf, dname_len);
643 	if(!(*qinfo)->qname) fatal_exit("out of memory");
644 	(*qinfo)->qname_len = dname_len;
645 	(*qinfo)->qtype = sldns_wirerr_get_type(buf, len, dname_len);
646 	(*qinfo)->qclass = sldns_wirerr_get_class(buf, len, dname_len);
647 }
648 
649 /** print flags to string */
650 static void
651 pr_flags(sldns_buffer* buf, uint16_t flags)
652 {
653 	char rcode[32];
654 	sldns_buffer_printf(buf, ";flags");
655 	if((flags&BIT_QR)!=0) sldns_buffer_printf(buf, " QR");
656 	if((flags&BIT_AA)!=0) sldns_buffer_printf(buf, " AA");
657 	if((flags&BIT_TC)!=0) sldns_buffer_printf(buf, " TC");
658 	if((flags&BIT_RD)!=0) sldns_buffer_printf(buf, " RD");
659 	if((flags&BIT_CD)!=0) sldns_buffer_printf(buf, " CD");
660 	if((flags&BIT_RA)!=0) sldns_buffer_printf(buf, " RA");
661 	if((flags&BIT_AD)!=0) sldns_buffer_printf(buf, " AD");
662 	if((flags&BIT_Z)!=0) sldns_buffer_printf(buf, " Z");
663 	sldns_wire2str_rcode_buf((int)(FLAGS_GET_RCODE(flags)),
664 		rcode, sizeof(rcode));
665 	sldns_buffer_printf(buf, " rcode %s", rcode);
666 	sldns_buffer_printf(buf, "\n");
667 }
668 
669 /** print RRs to string */
670 static void
671 pr_rrs(sldns_buffer* buf, struct reply_info* rep)
672 {
673 	char s[65536];
674 	size_t i, j;
675 	struct packed_rrset_data* d;
676 	log_assert(rep->rrset_count == rep->an_numrrsets + rep->ns_numrrsets
677 		+ rep->ar_numrrsets);
678 	for(i=0; i<rep->rrset_count; i++) {
679 		/* section heading */
680 		if(i == 0 && rep->an_numrrsets != 0)
681 			sldns_buffer_printf(buf, ";answer section\n");
682 		else if(i == rep->an_numrrsets && rep->ns_numrrsets != 0)
683 			sldns_buffer_printf(buf, ";authority section\n");
684 		else if(i == rep->an_numrrsets+rep->ns_numrrsets &&
685 			rep->ar_numrrsets != 0)
686 			sldns_buffer_printf(buf, ";additional section\n");
687 		/* spool RRset */
688 		d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data;
689 		for(j=0; j<d->count+d->rrsig_count; j++) {
690 			if(!packed_rr_to_string(rep->rrsets[i], j, 0,
691 				s, sizeof(s))) {
692 				fatal_exit("could not rr_to_string %d",
693 					(int)i);
694 			}
695 			sldns_buffer_printf(buf, "%s", s);
696 		}
697 	}
698 }
699 
700 /** create string for message */
701 static char*
702 msgtostr(struct dns_msg* msg)
703 {
704 	char* str;
705 	sldns_buffer* buf = sldns_buffer_new(65535);
706 	if(!buf) fatal_exit("out of memory");
707 	if(!msg) {
708 		sldns_buffer_printf(buf, "null packet\n");
709 	} else {
710 		pr_flags(buf, msg->rep->flags);
711 		pr_rrs(buf, msg->rep);
712 	}
713 
714 	str = strdup((char*)sldns_buffer_begin(buf));
715 	if(!str) fatal_exit("out of memory");
716 	sldns_buffer_free(buf);
717 	return str;
718 }
719 
720 /** find line diff between strings */
721 static void
722 line_diff(const char* p, const char* q, const char* pdesc, const char* qdesc)
723 {
724 	char* pdup, *qdup, *pl, *ql;
725 	int line = 1;
726 	pdup = strdup(p);
727 	qdup = strdup(q);
728 	if(!pdup || !qdup) fatal_exit("out of memory");
729 	pl=pdup;
730 	ql=qdup;
731 	printf("linediff (<%s, >%s)\n", pdesc, qdesc);
732 	while(pl && ql && *pl && *ql) {
733 		char* ep = strchr(pl, '\n');
734 		char* eq = strchr(ql, '\n');
735 		/* terminate lines */
736 		if(ep) *ep = 0;
737 		if(eq) *eq = 0;
738 		/* printout */
739 		if(strcmp(pl, ql) == 0) {
740 			printf("%3d   %s\n", line, pl);
741 		} else {
742 			printf("%3d < %s\n", line, pl);
743 			printf("%3d > %s\n", line, ql);
744 		}
745 		if(ep) *ep = '\n';
746 		if(eq) *eq = '\n';
747 		if(ep) pl = ep+1;
748 		else pl = NULL;
749 		if(eq) ql = eq+1;
750 		else ql = NULL;
751 		line++;
752 	}
753 	if(pl && *pl) {
754 		printf("%3d < %s\n", line, pl);
755 	}
756 	if(ql && *ql) {
757 		printf("%3d > %s\n", line, ql);
758 	}
759 	free(pdup);
760 	free(qdup);
761 }
762 
763 /** make q_ans query */
764 static void
765 q_ans_query(struct q_ans* q, struct auth_zones* az, struct query_info* qinfo,
766 	struct regional* region, int expected_fallback, uint8_t* dp_nm,
767 	size_t dp_nmlen)
768 {
769 	int ret, fallback = 0;
770 	struct dns_msg* msg = NULL;
771 	char* ans_str;
772 	int oldv = verbosity;
773 	/* increase verbosity to printout logic in authzone */
774 	if(vbmp) verbosity = 4;
775 	ret = auth_zones_lookup(az, qinfo, region, &msg, &fallback, dp_nm,
776 		dp_nmlen);
777 	if(vbmp) verbosity = oldv;
778 
779 	/* check the answer */
780 	ans_str = msgtostr(msg);
781 	/* printout if vbmp */
782 	if(vbmp) printf("got (ret=%s%s):\n%s",
783 		(ret?"ok":"fail"), (fallback?" fallback":""), ans_str);
784 	/* check expected value for ret */
785 	if(expected_fallback && ret != 0) {
786 		/* ret is zero on fallback */
787 		if(vbmp) printf("fallback expected, but "
788 			"return value is not false\n");
789 		unit_assert(expected_fallback && ret == 0);
790 	}
791 	if(ret == 0) {
792 		if(!expected_fallback) {
793 			if(vbmp) printf("return value is false, "
794 				"(unexpected)\n");
795 		}
796 		unit_assert(expected_fallback);
797 	}
798 	/* check expected value for fallback */
799 	if(expected_fallback && !fallback) {
800 		if(vbmp) printf("expected fallback, but fallback is no\n");
801 	} else if(!expected_fallback && fallback) {
802 		if(vbmp) printf("expected no fallback, but fallback is yes\n");
803 	}
804 	unit_assert( (expected_fallback&&fallback) ||
805 		(!expected_fallback&&!fallback));
806 	/* check answer string */
807 	if(strcmp(q->answer, ans_str) != 0) {
808 		if(vbmp) printf("wanted:\n%s", q->answer);
809 		line_diff(q->answer, ans_str, "wanted", "got");
810 	}
811 	unit_assert(strcmp(q->answer, ans_str) == 0);
812 	if(vbmp) printf("query ok\n\n");
813 	free(ans_str);
814 }
815 
816 /** check queries on a loaded zone */
817 static void
818 check_az_q_ans(struct auth_zones* az, struct q_ans* queries)
819 {
820 	struct q_ans* q;
821 	struct regional* region = regional_create();
822 	struct query_info* qinfo;
823 	int fallback;
824 	uint8_t* dp_nm;
825 	size_t dp_nmlen;
826 	for(q=queries; q->zone; q++) {
827 		if(vbmp) printf("query %s: %s %s\n", q->zone, q->query,
828 			q->flags);
829 		q_ans_parse(q, region, &qinfo, &fallback, &dp_nm, &dp_nmlen);
830 		q_ans_query(q, az, qinfo, region, fallback, dp_nm, dp_nmlen);
831 		regional_free_all(region);
832 	}
833 	regional_destroy(region);
834 }
835 
836 /** check queries for a zone are returned as specified */
837 static void
838 check_queries(const char* name, const char* zone, struct q_ans* queries)
839 {
840 	struct auth_zones* az;
841 	struct auth_zone* z;
842 	char* fname;
843 	if(vbmp) printf("check queries %s\n", name);
844 	fname = create_tmp_file(zone);
845 	az = auth_zones_create();
846 	if(!az) fatal_exit("out of memory");
847 	z = addzone(az, name, fname);
848 	if(!z) fatal_exit("could not read zone for queries test");
849 	del_tmp_file(fname);
850 
851 	/* run queries and test them */
852 	check_az_q_ans(az, queries);
853 
854 	auth_zones_delete(az);
855 }
856 
857 /** Test authzone compare_serial */
858 static void
859 authzone_compare_serial(void)
860 {
861 	if(vbmp) printf("Testing compare_serial\n");
862 	unit_assert(compare_serial(0, 1) < 0);
863 	unit_assert(compare_serial(1, 0) > 0);
864 	unit_assert(compare_serial(0, 0) == 0);
865 	unit_assert(compare_serial(1, 1) == 0);
866 	unit_assert(compare_serial(0xf0000000, 0xf0000000) == 0);
867 	unit_assert(compare_serial(0, 0xf0000000) > 0);
868 	unit_assert(compare_serial(0xf0000000, 0) < 0);
869 	unit_assert(compare_serial(0xf0000000, 0xf0000001) < 0);
870 	unit_assert(compare_serial(0xf0000002, 0xf0000001) > 0);
871 	unit_assert(compare_serial(0x70000000, 0x80000000) < 0);
872 	unit_assert(compare_serial(0x90000000, 0x70000000) > 0);
873 }
874 
875 /** Test authzone read from file */
876 static void
877 authzone_read_test(void)
878 {
879 	if(vbmp) printf("Testing read auth zone\n");
880 	check_read_exact("example.com", zone_example_com);
881 }
882 
883 /** Test authzone query from zone */
884 static void
885 authzone_query_test(void)
886 {
887 	if(vbmp) printf("Testing query auth zone\n");
888 	check_queries("example.com", zone_example_com, example_com_queries);
889 }
890 
891 /** test authzone code */
892 void
893 authzone_test(void)
894 {
895 	unit_show_feature("authzone");
896 	atexit(tmpfilecleanup);
897 	authzone_compare_serial();
898 	authzone_read_test();
899 	authzone_query_test();
900 }
901