]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/lib/dns/private.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / bind9 / lib / dns / private.c
1 /*
2  * Copyright (C) 2009, 2012  Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /* $Id$ */
18
19 #include "config.h"
20
21 #include <isc/result.h>
22 #include <isc/string.h>
23 #include <isc/types.h>
24 #include <isc/base64.h>
25
26 #include <dns/nsec3.h>
27 #include <dns/private.h>
28
29 /*
30  * We need to build the relevant chain if there exists a NSEC/NSEC3PARAM
31  * at the apex; normally only one or the other of NSEC/NSEC3PARAM will exist.
32  *
33  * If a NSEC3PARAM RRset exists then we will need to build a NSEC chain
34  * if all the NSEC3PARAM records (and associated chains) are slated for
35  * destruction and we have not been told to NOT build the NSEC chain.
36  *
37  * If the NSEC set exist then check to see if there is a request to create
38  * a NSEC3 chain.
39  *
40  * If neither NSEC/NSEC3PARAM RRsets exist at the origin and the private
41  * type exists then we need to examine it to determine if NSEC3 chain has
42  * been requested to be built otherwise a NSEC chain needs to be built.
43  */
44
45 #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
46 #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
47 #define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0)
48
49 #define CHECK(x) do {                                   \
50                          result = (x);                  \
51                          if (result != ISC_R_SUCCESS)   \
52                                 goto failure;           \
53                  } while (0)
54
55 /*
56  * Work out if 'param' should be ignored or not (i.e. it is in the process
57  * of being removed).
58  *
59  * Note: we 'belt-and-braces' here by also checking for a CREATE private
60  * record and keep the param record in this case.
61  */
62
63 static isc_boolean_t
64 ignore(dns_rdata_t *param, dns_rdataset_t *privateset) {
65         isc_result_t result;
66
67         for (result = dns_rdataset_first(privateset);
68              result == ISC_R_SUCCESS;
69              result = dns_rdataset_next(privateset)) {
70                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
71                 dns_rdata_t private = DNS_RDATA_INIT;
72                 dns_rdata_t rdata = DNS_RDATA_INIT;
73
74                 dns_rdataset_current(privateset, &private);
75                 if (!dns_nsec3param_fromprivate(&private, &rdata,
76                                                 buf, sizeof(buf)))
77                         continue;
78                 /*
79                  * We are going to create a new NSEC3 chain so it
80                  * doesn't matter if we are removing this one.
81                  */
82                 if (CREATE(rdata.data[1]))
83                         return (ISC_FALSE);
84                 if (rdata.data[0] != param->data[0] ||
85                     rdata.data[2] != param->data[2] ||
86                     rdata.data[3] != param->data[3] ||
87                     rdata.data[4] != param->data[4] ||
88                     memcmp(&rdata.data[5], &param->data[5], param->data[4]))
89                         continue;
90                 /*
91                  * The removal of this NSEC3 chain does NOT cause a
92                  * NSEC chain to be created so we don't need to tell
93                  * the caller that it will be removed.
94                  */
95                 if (NONSEC(rdata.data[1]))
96                         return (ISC_FALSE);
97                 return (ISC_TRUE);
98         }
99         return (ISC_FALSE);
100 }
101
102 isc_result_t
103 dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
104                    dns_rdatatype_t privatetype,
105                    isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3)
106 {
107         dns_dbnode_t *node;
108         dns_rdataset_t nsecset, nsec3paramset, privateset;
109         isc_boolean_t nsec3chain;
110         isc_boolean_t signing;
111         isc_result_t result;
112         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
113         unsigned int count;
114
115         node = NULL;
116         dns_rdataset_init(&nsecset);
117         dns_rdataset_init(&nsec3paramset);
118         dns_rdataset_init(&privateset);
119
120         CHECK(dns_db_getoriginnode(db, &node));
121
122         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
123                                      0, (isc_stdtime_t) 0, &nsecset, NULL);
124
125         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
126                 goto failure;
127
128         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
129                                      0, (isc_stdtime_t) 0, &nsec3paramset,
130                                      NULL);
131         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
132                 goto failure;
133
134         if (dns_rdataset_isassociated(&nsecset) &&
135             dns_rdataset_isassociated(&nsec3paramset)) {
136                 if (build_nsec != NULL)
137                         *build_nsec = ISC_TRUE;
138                 if (build_nsec3 != NULL)
139                         *build_nsec3 = ISC_TRUE;
140                 goto success;
141         }
142
143         if (privatetype != (dns_rdatatype_t)0) {
144                 result = dns_db_findrdataset(db, node, ver, privatetype,
145                                              0, (isc_stdtime_t) 0,
146                                              &privateset, NULL);
147                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
148                         goto failure;
149         }
150
151         /*
152          * Look to see if we also need to be creating a NSEC3 chains.
153          */
154         if (dns_rdataset_isassociated(&nsecset)) {
155                 if (build_nsec != NULL)
156                         *build_nsec = ISC_TRUE;
157                 if (build_nsec3 != NULL)
158                         *build_nsec3 = ISC_FALSE;
159                 if (!dns_rdataset_isassociated(&privateset))
160                         goto success;
161                 for (result = dns_rdataset_first(&privateset);
162                      result == ISC_R_SUCCESS;
163                      result = dns_rdataset_next(&privateset)) {
164                         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
165                         dns_rdata_t private = DNS_RDATA_INIT;
166                         dns_rdata_t rdata = DNS_RDATA_INIT;
167
168                         dns_rdataset_current(&privateset, &private);
169                         if (!dns_nsec3param_fromprivate(&private, &rdata,
170                                                         buf, sizeof(buf)))
171                                 continue;
172                         if (REMOVE(rdata.data[1]))
173                                 continue;
174                         if (build_nsec3 != NULL)
175                                 *build_nsec3 = ISC_TRUE;
176                         break;
177                 }
178                 goto success;
179         }
180
181         if (dns_rdataset_isassociated(&nsec3paramset)) {
182                 if (build_nsec3 != NULL)
183                         *build_nsec3 = ISC_TRUE;
184                 if (build_nsec != NULL)
185                         *build_nsec = ISC_FALSE;
186                 if (!dns_rdataset_isassociated(&privateset))
187                         goto success;
188                 /*
189                  * If we are in the process of building a new NSEC3 chain
190                  * then we don't need to build a NSEC chain.
191                  */
192                 for (result = dns_rdataset_first(&privateset);
193                      result == ISC_R_SUCCESS;
194                      result = dns_rdataset_next(&privateset)) {
195                         dns_rdata_t private = DNS_RDATA_INIT;
196                         dns_rdata_t rdata = DNS_RDATA_INIT;
197
198                         dns_rdataset_current(&privateset, &private);
199                         if (!dns_nsec3param_fromprivate(&private, &rdata,
200                                                         buf, sizeof(buf)))
201                                 continue;
202                         if (CREATE(rdata.data[1]))
203                                 goto success;
204                 }
205
206                 /*
207                  * Check to see if there will be a active NSEC3CHAIN once
208                  * the changes queued complete.
209                  */
210                 count = 0;
211                 for (result = dns_rdataset_first(&nsec3paramset);
212                      result == ISC_R_SUCCESS;
213                      result = dns_rdataset_next(&nsec3paramset)) {
214                         dns_rdata_t rdata = DNS_RDATA_INIT;
215
216                         /*
217                          * If there is more that one NSEC3 chain present then
218                          * we don't need to construct a NSEC chain.
219                          */
220                         if (++count > 1)
221                                 goto success;
222                         dns_rdataset_current(&nsec3paramset, &rdata);
223                         if (ignore(&rdata, &privateset))
224                                 continue;
225                         /*
226                          * We still have a good NSEC3 chain or we are
227                          * not creating a NSEC chain as NONSEC is set.
228                          */
229                         goto success;
230                 }
231
232                 /*
233                  * The last NSEC3 chain is being removed and does not have
234                  * have NONSEC set.
235                  */
236                 if (build_nsec != NULL)
237                         *build_nsec = ISC_TRUE;
238                 goto success;
239         }
240
241         if (build_nsec != NULL)
242                 *build_nsec = ISC_FALSE;
243         if (build_nsec3 != NULL)
244                 *build_nsec3 = ISC_FALSE;
245         if (!dns_rdataset_isassociated(&privateset))
246                 goto success;
247
248         signing = ISC_FALSE;
249         nsec3chain = ISC_FALSE;
250
251         for (result = dns_rdataset_first(&privateset);
252              result == ISC_R_SUCCESS;
253              result = dns_rdataset_next(&privateset)) {
254                 dns_rdata_t rdata = DNS_RDATA_INIT;
255                 dns_rdata_t private = DNS_RDATA_INIT;
256
257                 dns_rdataset_current(&privateset, &private);
258                 if (!dns_nsec3param_fromprivate(&private, &rdata,
259                                                 buf, sizeof(buf))) {
260                         /*
261                          * Look for record that says we are signing the
262                          * zone with a key.
263                          */
264                         if (private.length == 5 && private.data[0] != 0 &&
265                             private.data[3] == 0 && private.data[4] == 0)
266                                 signing = ISC_TRUE;
267                 } else {
268                         if (CREATE(rdata.data[1]))
269                                 nsec3chain = ISC_TRUE;
270                 }
271         }
272
273         if (signing) {
274                 if (nsec3chain) {
275                         if (build_nsec3 != NULL)
276                                 *build_nsec3 = ISC_TRUE;
277                 } else {
278                         if (build_nsec != NULL)
279                                 *build_nsec = ISC_TRUE;
280                 }
281         }
282
283  success:
284         result = ISC_R_SUCCESS;
285  failure:
286         if (dns_rdataset_isassociated(&nsecset))
287                 dns_rdataset_disassociate(&nsecset);
288         if (dns_rdataset_isassociated(&nsec3paramset))
289                 dns_rdataset_disassociate(&nsec3paramset);
290         if (dns_rdataset_isassociated(&privateset))
291                 dns_rdataset_disassociate(&privateset);
292         if (node != NULL)
293                 dns_db_detachnode(db, &node);
294         return (result);
295 }