]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - testcode/unitauth.c
Vendor import of Unbound 1.9.0.
[FreeBSD/FreeBSD.git] / testcode / unitauth.c
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 }