]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/bind9/lib/dns/private.c
Copy stable/9 to releng/9.3 as part of the 9.3-RELEASE cycle.
[FreeBSD/releng/9.3.git] / contrib / bind9 / lib / dns / private.c
1 /*
2  * Copyright (C) 2009, 2011, 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 INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0)
48 #define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0)
49
50 #define CHECK(x) do {                                   \
51                          result = (x);                  \
52                          if (result != ISC_R_SUCCESS)   \
53                                 goto failure;           \
54                  } while (0)
55
56 /*
57  * Work out if 'param' should be ignored or not (i.e. it is in the process
58  * of being removed).
59  *
60  * Note: we 'belt-and-braces' here by also checking for a CREATE private
61  * record and keep the param record in this case.
62  */
63
64 static isc_boolean_t
65 ignore(dns_rdata_t *param, dns_rdataset_t *privateset) {
66         isc_result_t result;
67
68         for (result = dns_rdataset_first(privateset);
69              result == ISC_R_SUCCESS;
70              result = dns_rdataset_next(privateset)) {
71                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
72                 dns_rdata_t private = DNS_RDATA_INIT;
73                 dns_rdata_t rdata = DNS_RDATA_INIT;
74
75                 dns_rdataset_current(privateset, &private);
76                 if (!dns_nsec3param_fromprivate(&private, &rdata,
77                                                 buf, sizeof(buf)))
78                         continue;
79                 /*
80                  * We are going to create a new NSEC3 chain so it
81                  * doesn't matter if we are removing this one.
82                  */
83                 if (CREATE(rdata.data[1]))
84                         return (ISC_FALSE);
85                 if (rdata.data[0] != param->data[0] ||
86                     rdata.data[2] != param->data[2] ||
87                     rdata.data[3] != param->data[3] ||
88                     rdata.data[4] != param->data[4] ||
89                     memcmp(&rdata.data[5], &param->data[5], param->data[4]))
90                         continue;
91                 /*
92                  * The removal of this NSEC3 chain does NOT cause a
93                  * NSEC chain to be created so we don't need to tell
94                  * the caller that it will be removed.
95                  */
96                 if (NONSEC(rdata.data[1]))
97                         return (ISC_FALSE);
98                 return (ISC_TRUE);
99         }
100         return (ISC_FALSE);
101 }
102
103 isc_result_t
104 dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
105                    dns_rdatatype_t privatetype,
106                    isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3)
107 {
108         dns_dbnode_t *node;
109         dns_rdataset_t nsecset, nsec3paramset, privateset;
110         isc_boolean_t nsec3chain;
111         isc_boolean_t signing;
112         isc_result_t result;
113         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
114         unsigned int count;
115
116         node = NULL;
117         dns_rdataset_init(&nsecset);
118         dns_rdataset_init(&nsec3paramset);
119         dns_rdataset_init(&privateset);
120
121         CHECK(dns_db_getoriginnode(db, &node));
122
123         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
124                                      0, (isc_stdtime_t) 0, &nsecset, NULL);
125
126         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
127                 goto failure;
128
129         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
130                                      0, (isc_stdtime_t) 0, &nsec3paramset,
131                                      NULL);
132         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
133                 goto failure;
134
135         if (dns_rdataset_isassociated(&nsecset) &&
136             dns_rdataset_isassociated(&nsec3paramset)) {
137                 if (build_nsec != NULL)
138                         *build_nsec = ISC_TRUE;
139                 if (build_nsec3 != NULL)
140                         *build_nsec3 = ISC_TRUE;
141                 goto success;
142         }
143
144         if (privatetype != (dns_rdatatype_t)0) {
145                 result = dns_db_findrdataset(db, node, ver, privatetype,
146                                              0, (isc_stdtime_t) 0,
147                                              &privateset, NULL);
148                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
149                         goto failure;
150         }
151
152         /*
153          * Look to see if we also need to be creating a NSEC3 chain.
154          */
155         if (dns_rdataset_isassociated(&nsecset)) {
156                 if (build_nsec != NULL)
157                         *build_nsec = ISC_TRUE;
158                 if (build_nsec3 != NULL)
159                         *build_nsec3 = ISC_FALSE;
160                 if (!dns_rdataset_isassociated(&privateset))
161                         goto success;
162                 for (result = dns_rdataset_first(&privateset);
163                      result == ISC_R_SUCCESS;
164                      result = dns_rdataset_next(&privateset)) {
165                         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
166                         dns_rdata_t private = DNS_RDATA_INIT;
167                         dns_rdata_t rdata = DNS_RDATA_INIT;
168
169                         dns_rdataset_current(&privateset, &private);
170                         if (!dns_nsec3param_fromprivate(&private, &rdata,
171                                                         buf, sizeof(buf)))
172                                 continue;
173                         if (REMOVE(rdata.data[1]))
174                                 continue;
175                         if (build_nsec3 != NULL)
176                                 *build_nsec3 = ISC_TRUE;
177                         break;
178                 }
179                 goto success;
180         }
181
182         if (dns_rdataset_isassociated(&nsec3paramset)) {
183                 if (build_nsec3 != NULL)
184                         *build_nsec3 = ISC_TRUE;
185                 if (build_nsec != NULL)
186                         *build_nsec = ISC_FALSE;
187                 if (!dns_rdataset_isassociated(&privateset))
188                         goto success;
189                 /*
190                  * If we are in the process of building a new NSEC3 chain
191                  * then we don't need to build a NSEC chain.
192                  */
193                 for (result = dns_rdataset_first(&privateset);
194                      result == ISC_R_SUCCESS;
195                      result = dns_rdataset_next(&privateset)) {
196                         dns_rdata_t private = DNS_RDATA_INIT;
197                         dns_rdata_t rdata = DNS_RDATA_INIT;
198
199                         dns_rdataset_current(&privateset, &private);
200                         if (!dns_nsec3param_fromprivate(&private, &rdata,
201                                                         buf, sizeof(buf)))
202                                 continue;
203                         if (CREATE(rdata.data[1]))
204                                 goto success;
205                 }
206
207                 /*
208                  * Check to see if there will be a active NSEC3CHAIN once
209                  * the changes queued complete.
210                  */
211                 count = 0;
212                 for (result = dns_rdataset_first(&nsec3paramset);
213                      result == ISC_R_SUCCESS;
214                      result = dns_rdataset_next(&nsec3paramset)) {
215                         dns_rdata_t rdata = DNS_RDATA_INIT;
216
217                         /*
218                          * If there is more that one NSEC3 chain present then
219                          * we don't need to construct a NSEC chain.
220                          */
221                         if (++count > 1)
222                                 goto success;
223                         dns_rdataset_current(&nsec3paramset, &rdata);
224                         if (ignore(&rdata, &privateset))
225                                 continue;
226                         /*
227                          * We still have a good NSEC3 chain or we are
228                          * not creating a NSEC chain as NONSEC is set.
229                          */
230                         goto success;
231                 }
232
233                 /*
234                  * The last NSEC3 chain is being removed and does not have
235                  * have NONSEC set.
236                  */
237                 if (build_nsec != NULL)
238                         *build_nsec = ISC_TRUE;
239                 goto success;
240         }
241
242         if (build_nsec != NULL)
243                 *build_nsec = ISC_FALSE;
244         if (build_nsec3 != NULL)
245                 *build_nsec3 = ISC_FALSE;
246         if (!dns_rdataset_isassociated(&privateset))
247                 goto success;
248
249         signing = ISC_FALSE;
250         nsec3chain = ISC_FALSE;
251
252         for (result = dns_rdataset_first(&privateset);
253              result == ISC_R_SUCCESS;
254              result = dns_rdataset_next(&privateset)) {
255                 dns_rdata_t rdata = DNS_RDATA_INIT;
256                 dns_rdata_t private = DNS_RDATA_INIT;
257
258                 dns_rdataset_current(&privateset, &private);
259                 if (!dns_nsec3param_fromprivate(&private, &rdata,
260                                                 buf, sizeof(buf))) {
261                         /*
262                          * Look for record that says we are signing the
263                          * zone with a key.
264                          */
265                         if (private.length == 5 && private.data[0] != 0 &&
266                             private.data[3] == 0 && private.data[4] == 0)
267                                 signing = ISC_TRUE;
268                 } else {
269                         if (CREATE(rdata.data[1]))
270                                 nsec3chain = ISC_TRUE;
271                 }
272         }
273
274         if (signing) {
275                 if (nsec3chain) {
276                         if (build_nsec3 != NULL)
277                                 *build_nsec3 = ISC_TRUE;
278                 } else {
279                         if (build_nsec != NULL)
280                                 *build_nsec = ISC_TRUE;
281                 }
282         }
283
284  success:
285         result = ISC_R_SUCCESS;
286  failure:
287         if (dns_rdataset_isassociated(&nsecset))
288                 dns_rdataset_disassociate(&nsecset);
289         if (dns_rdataset_isassociated(&nsec3paramset))
290                 dns_rdataset_disassociate(&nsec3paramset);
291         if (dns_rdataset_isassociated(&privateset))
292                 dns_rdataset_disassociate(&privateset);
293         if (node != NULL)
294                 dns_db_detachnode(db, &node);
295         return (result);
296 }
297
298 isc_result_t
299 dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
300         isc_result_t result;
301
302         if (private->length < 5)
303                 return (ISC_R_NOTFOUND);
304
305         if (private->data[0] == 0) {
306                 unsigned char nsec3buf[DNS_NSEC3PARAM_BUFFERSIZE];
307                 unsigned char newbuf[DNS_NSEC3PARAM_BUFFERSIZE];
308                 dns_rdata_t rdata = DNS_RDATA_INIT;
309                 dns_rdata_nsec3param_t nsec3param;
310                 isc_boolean_t remove, init, nonsec;
311                 isc_buffer_t b;
312
313                 if (!dns_nsec3param_fromprivate(private, &rdata, nsec3buf,
314                                                 sizeof(nsec3buf)))
315                         CHECK(ISC_R_FAILURE);
316
317                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
318
319                 remove = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0);
320                 init = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0);
321                 nonsec = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_NONSEC) != 0);
322
323                 nsec3param.flags &= ~(DNS_NSEC3FLAG_CREATE|
324                                       DNS_NSEC3FLAG_REMOVE|
325                                       DNS_NSEC3FLAG_INITIAL|
326                                       DNS_NSEC3FLAG_NONSEC);
327
328                 if (init)
329                         isc_buffer_putstr(buf, "Pending NSEC3 chain ");
330                 else if (remove)
331                         isc_buffer_putstr(buf, "Removing NSEC3 chain ");
332                 else
333                         isc_buffer_putstr(buf, "Creating NSEC3 chain ");
334
335                 dns_rdata_reset(&rdata);
336                 isc_buffer_init(&b, newbuf, sizeof(newbuf));
337                 CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_in,
338                                            dns_rdatatype_nsec3param,
339                                            &nsec3param, &b));
340
341                 CHECK(dns_rdata_totext(&rdata, NULL, buf));
342
343                 if (remove && !nonsec)
344                         isc_buffer_putstr(buf, " / creating NSEC chain");
345         } else if (private->length == 5) {
346                 unsigned char alg = private->data[0];
347                 dns_keytag_t keyid = (private->data[2] | private->data[1] << 8);
348                 char keybuf[BUFSIZ], algbuf[DNS_SECALG_FORMATSIZE];
349                 isc_boolean_t remove = ISC_TF(private->data[3] != 0);
350                 isc_boolean_t complete = ISC_TF(private->data[4] != 0);
351
352                 if (remove && complete)
353                         isc_buffer_putstr(buf, "Done removing signatures for ");
354                 else if (remove)
355                         isc_buffer_putstr(buf, "Removing signatures for ");
356                 else if (complete)
357                         isc_buffer_putstr(buf, "Done signing with ");
358                 else
359                         isc_buffer_putstr(buf, "Signing with ");
360
361                 dns_secalg_format(alg, algbuf, sizeof(algbuf));
362                 sprintf(keybuf, "key %d/%s", keyid, algbuf);
363                 isc_buffer_putstr(buf, keybuf);
364         } else
365                 return (ISC_R_NOTFOUND);
366
367         isc_buffer_putuint8(buf, 0);
368         result = ISC_R_SUCCESS;
369  failure:
370         return (result);
371 }