private.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2009, 2011, 2012, 2015  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /* $Id$ */
00018 
00019 #include "config.h"
00020 
00021 #include <isc/result.h>
00022 #include <isc/string.h>
00023 #include <isc/types.h>
00024 #include <isc/base64.h>
00025 
00026 #include <dns/nsec3.h>
00027 #include <dns/private.h>
00028 
00029 /*
00030  * We need to build the relevant chain if there exists a NSEC/NSEC3PARAM
00031  * at the apex; normally only one or the other of NSEC/NSEC3PARAM will exist.
00032  *
00033  * If a NSEC3PARAM RRset exists then we will need to build a NSEC chain
00034  * if all the NSEC3PARAM records (and associated chains) are slated for
00035  * destruction and we have not been told to NOT build the NSEC chain.
00036  *
00037  * If the NSEC set exist then check to see if there is a request to create
00038  * a NSEC3 chain.
00039  *
00040  * If neither NSEC/NSEC3PARAM RRsets exist at the origin and the private
00041  * type exists then we need to examine it to determine if NSEC3 chain has
00042  * been requested to be built otherwise a NSEC chain needs to be built.
00043  */
00044 
00045 #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
00046 #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
00047 #define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0)
00048 #define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0)
00049 
00050 #define CHECK(x) do {                                   \
00051                          result = (x);                  \
00052                          if (result != ISC_R_SUCCESS)   \
00053                                 goto failure;           \
00054                  } while (0)
00055 
00056 /*
00057  * Work out if 'param' should be ignored or not (i.e. it is in the process
00058  * of being removed).
00059  *
00060  * Note: we 'belt-and-braces' here by also checking for a CREATE private
00061  * record and keep the param record in this case.
00062  */
00063 
00064 static isc_boolean_t
00065 ignore(dns_rdata_t *param, dns_rdataset_t *privateset) {
00066         isc_result_t result;
00067 
00068         for (result = dns_rdataset_first(privateset);
00069              result == ISC_R_SUCCESS;
00070              result = dns_rdataset_next(privateset)) {
00071                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
00072                 dns_rdata_t private = DNS_RDATA_INIT;
00073                 dns_rdata_t rdata = DNS_RDATA_INIT;
00074 
00075                 dns_rdataset_current(privateset, &private);
00076                 if (!dns_nsec3param_fromprivate(&private, &rdata,
00077                                                 buf, sizeof(buf)))
00078                         continue;
00079                 /*
00080                  * We are going to create a new NSEC3 chain so it
00081                  * doesn't matter if we are removing this one.
00082                  */
00083                 if (CREATE(rdata.data[1]))
00084                         return (ISC_FALSE);
00085                 if (rdata.data[0] != param->data[0] ||
00086                     rdata.data[2] != param->data[2] ||
00087                     rdata.data[3] != param->data[3] ||
00088                     rdata.data[4] != param->data[4] ||
00089                     memcmp(&rdata.data[5], &param->data[5], param->data[4]))
00090                         continue;
00091                 /*
00092                  * The removal of this NSEC3 chain does NOT cause a
00093                  * NSEC chain to be created so we don't need to tell
00094                  * the caller that it will be removed.
00095                  */
00096                 if (NONSEC(rdata.data[1]))
00097                         return (ISC_FALSE);
00098                 return (ISC_TRUE);
00099         }
00100         return (ISC_FALSE);
00101 }
00102 
00103 isc_result_t
00104 dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
00105                    dns_rdatatype_t privatetype,
00106                    isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3)
00107 {
00108         dns_dbnode_t *node;
00109         dns_rdataset_t nsecset, nsec3paramset, privateset;
00110         isc_boolean_t nsec3chain;
00111         isc_boolean_t signing;
00112         isc_result_t result;
00113         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
00114         unsigned int count;
00115 
00116         node = NULL;
00117         dns_rdataset_init(&nsecset);
00118         dns_rdataset_init(&nsec3paramset);
00119         dns_rdataset_init(&privateset);
00120 
00121         CHECK(dns_db_getoriginnode(db, &node));
00122 
00123         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
00124                                      0, (isc_stdtime_t) 0, &nsecset, NULL);
00125 
00126         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
00127                 goto failure;
00128 
00129         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
00130                                      0, (isc_stdtime_t) 0, &nsec3paramset,
00131                                      NULL);
00132         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
00133                 goto failure;
00134 
00135         if (dns_rdataset_isassociated(&nsecset) &&
00136             dns_rdataset_isassociated(&nsec3paramset)) {
00137                 if (build_nsec != NULL)
00138                         *build_nsec = ISC_TRUE;
00139                 if (build_nsec3 != NULL)
00140                         *build_nsec3 = ISC_TRUE;
00141                 goto success;
00142         }
00143 
00144         if (privatetype != (dns_rdatatype_t)0) {
00145                 result = dns_db_findrdataset(db, node, ver, privatetype,
00146                                              0, (isc_stdtime_t) 0,
00147                                              &privateset, NULL);
00148                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
00149                         goto failure;
00150         }
00151 
00152         /*
00153          * Look to see if we also need to be creating a NSEC3 chain.
00154          */
00155         if (dns_rdataset_isassociated(&nsecset)) {
00156                 if (build_nsec != NULL)
00157                         *build_nsec = ISC_TRUE;
00158                 if (build_nsec3 != NULL)
00159                         *build_nsec3 = ISC_FALSE;
00160                 if (!dns_rdataset_isassociated(&privateset))
00161                         goto success;
00162                 for (result = dns_rdataset_first(&privateset);
00163                      result == ISC_R_SUCCESS;
00164                      result = dns_rdataset_next(&privateset)) {
00165                         dns_rdata_t private = DNS_RDATA_INIT;
00166                         dns_rdata_t rdata = DNS_RDATA_INIT;
00167 
00168                         dns_rdataset_current(&privateset, &private);
00169                         if (!dns_nsec3param_fromprivate(&private, &rdata,
00170                                                         buf, sizeof(buf)))
00171                                 continue;
00172                         if (REMOVE(rdata.data[1]))
00173                                 continue;
00174                         if (build_nsec3 != NULL)
00175                                 *build_nsec3 = ISC_TRUE;
00176                         break;
00177                 }
00178                 goto success;
00179         }
00180 
00181         if (dns_rdataset_isassociated(&nsec3paramset)) {
00182                 if (build_nsec3 != NULL)
00183                         *build_nsec3 = ISC_TRUE;
00184                 if (build_nsec != NULL)
00185                         *build_nsec = ISC_FALSE;
00186                 if (!dns_rdataset_isassociated(&privateset))
00187                         goto success;
00188                 /*
00189                  * If we are in the process of building a new NSEC3 chain
00190                  * then we don't need to build a NSEC chain.
00191                  */
00192                 for (result = dns_rdataset_first(&privateset);
00193                      result == ISC_R_SUCCESS;
00194                      result = dns_rdataset_next(&privateset)) {
00195                         dns_rdata_t private = DNS_RDATA_INIT;
00196                         dns_rdata_t rdata = DNS_RDATA_INIT;
00197 
00198                         dns_rdataset_current(&privateset, &private);
00199                         if (!dns_nsec3param_fromprivate(&private, &rdata,
00200                                                         buf, sizeof(buf)))
00201                                 continue;
00202                         if (CREATE(rdata.data[1]))
00203                                 goto success;
00204                 }
00205 
00206                 /*
00207                  * Check to see if there will be a active NSEC3CHAIN once
00208                  * the changes queued complete.
00209                  */
00210                 count = 0;
00211                 for (result = dns_rdataset_first(&nsec3paramset);
00212                      result == ISC_R_SUCCESS;
00213                      result = dns_rdataset_next(&nsec3paramset)) {
00214                         dns_rdata_t rdata = DNS_RDATA_INIT;
00215 
00216                         /*
00217                          * If there is more that one NSEC3 chain present then
00218                          * we don't need to construct a NSEC chain.
00219                          */
00220                         if (++count > 1)
00221                                 goto success;
00222                         dns_rdataset_current(&nsec3paramset, &rdata);
00223                         if (ignore(&rdata, &privateset))
00224                                 continue;
00225                         /*
00226                          * We still have a good NSEC3 chain or we are
00227                          * not creating a NSEC chain as NONSEC is set.
00228                          */
00229                         goto success;
00230                 }
00231 
00232                 /*
00233                  * The last NSEC3 chain is being removed and does not have
00234                  * have NONSEC set.
00235                  */
00236                 if (build_nsec != NULL)
00237                         *build_nsec = ISC_TRUE;
00238                 goto success;
00239         }
00240 
00241         if (build_nsec != NULL)
00242                 *build_nsec = ISC_FALSE;
00243         if (build_nsec3 != NULL)
00244                 *build_nsec3 = ISC_FALSE;
00245         if (!dns_rdataset_isassociated(&privateset))
00246                 goto success;
00247 
00248         signing = ISC_FALSE;
00249         nsec3chain = ISC_FALSE;
00250 
00251         for (result = dns_rdataset_first(&privateset);
00252              result == ISC_R_SUCCESS;
00253              result = dns_rdataset_next(&privateset)) {
00254                 dns_rdata_t rdata = DNS_RDATA_INIT;
00255                 dns_rdata_t private = DNS_RDATA_INIT;
00256 
00257                 dns_rdataset_current(&privateset, &private);
00258                 if (!dns_nsec3param_fromprivate(&private, &rdata,
00259                                                 buf, sizeof(buf))) {
00260                         /*
00261                          * Look for record that says we are signing the
00262                          * zone with a key.
00263                          */
00264                         if (private.length == 5 && private.data[0] != 0 &&
00265                             private.data[3] == 0 && private.data[4] == 0)
00266                                 signing = ISC_TRUE;
00267                 } else {
00268                         if (CREATE(rdata.data[1]))
00269                                 nsec3chain = ISC_TRUE;
00270                 }
00271         }
00272 
00273         if (signing) {
00274                 if (nsec3chain) {
00275                         if (build_nsec3 != NULL)
00276                                 *build_nsec3 = ISC_TRUE;
00277                 } else {
00278                         if (build_nsec != NULL)
00279                                 *build_nsec = ISC_TRUE;
00280                 }
00281         }
00282 
00283  success:
00284         result = ISC_R_SUCCESS;
00285  failure:
00286         if (dns_rdataset_isassociated(&nsecset))
00287                 dns_rdataset_disassociate(&nsecset);
00288         if (dns_rdataset_isassociated(&nsec3paramset))
00289                 dns_rdataset_disassociate(&nsec3paramset);
00290         if (dns_rdataset_isassociated(&privateset))
00291                 dns_rdataset_disassociate(&privateset);
00292         if (node != NULL)
00293                 dns_db_detachnode(db, &node);
00294         return (result);
00295 }
00296 
00297 isc_result_t
00298 dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
00299         isc_result_t result;
00300 
00301         if (private->length < 5)
00302                 return (ISC_R_NOTFOUND);
00303 
00304         if (private->data[0] == 0) {
00305                 unsigned char nsec3buf[DNS_NSEC3PARAM_BUFFERSIZE];
00306                 unsigned char newbuf[DNS_NSEC3PARAM_BUFFERSIZE];
00307                 dns_rdata_t rdata = DNS_RDATA_INIT;
00308                 dns_rdata_nsec3param_t nsec3param;
00309                 isc_boolean_t delete, init, nonsec;
00310                 isc_buffer_t b;
00311 
00312                 if (!dns_nsec3param_fromprivate(private, &rdata, nsec3buf,
00313                                                 sizeof(nsec3buf)))
00314                         CHECK(ISC_R_FAILURE);
00315 
00316                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
00317 
00318                 delete = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0);
00319                 init = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0);
00320                 nonsec = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_NONSEC) != 0);
00321 
00322                 nsec3param.flags &= ~(DNS_NSEC3FLAG_CREATE|
00323                                       DNS_NSEC3FLAG_REMOVE|
00324                                       DNS_NSEC3FLAG_INITIAL|
00325                                       DNS_NSEC3FLAG_NONSEC);
00326 
00327                 if (init)
00328                         isc_buffer_putstr(buf, "Pending NSEC3 chain ");
00329                 else if (delete)
00330                         isc_buffer_putstr(buf, "Removing NSEC3 chain ");
00331                 else
00332                         isc_buffer_putstr(buf, "Creating NSEC3 chain ");
00333 
00334                 dns_rdata_reset(&rdata);
00335                 isc_buffer_init(&b, newbuf, sizeof(newbuf));
00336                 CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_in,
00337                                            dns_rdatatype_nsec3param,
00338                                            &nsec3param, &b));
00339 
00340                 CHECK(dns_rdata_totext(&rdata, NULL, buf));
00341 
00342                 if (delete && !nonsec)
00343                         isc_buffer_putstr(buf, " / creating NSEC chain");
00344         } else if (private->length == 5) {
00345                 unsigned char alg = private->data[0];
00346                 dns_keytag_t keyid = (private->data[2] | private->data[1] << 8);
00347                 char keybuf[BUFSIZ], algbuf[DNS_SECALG_FORMATSIZE];
00348                 isc_boolean_t delete = ISC_TF(private->data[3] != 0);
00349                 isc_boolean_t complete = ISC_TF(private->data[4] != 0);
00350 
00351                 if (delete && complete)
00352                         isc_buffer_putstr(buf, "Done removing signatures for ");
00353                 else if (delete)
00354                         isc_buffer_putstr(buf, "Removing signatures for ");
00355                 else if (complete)
00356                         isc_buffer_putstr(buf, "Done signing with ");
00357                 else
00358                         isc_buffer_putstr(buf, "Signing with ");
00359 
00360                 dns_secalg_format(alg, algbuf, sizeof(algbuf));
00361                 sprintf(keybuf, "key %d/%s", keyid, algbuf);
00362                 isc_buffer_putstr(buf, keybuf);
00363         } else
00364                 return (ISC_R_NOTFOUND);
00365 
00366         isc_buffer_putuint8(buf, 0);
00367         result = ISC_R_SUCCESS;
00368  failure:
00369         return (result);
00370 }

Generated on Tue Apr 28 17:40:59 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha