OpenDNSSEC-signer 1.3.0
|
00001 /* 00002 * $Id: tools.c 5320 2011-07-12 10:42:26Z jakob $ 00003 * 00004 * Copyright (c) 2009 NLNet Labs. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00020 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00023 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00024 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 * 00027 */ 00028 00034 #include "config.h" 00035 #include "adapter/adapter.h" 00036 #include "shared/file.h" 00037 #include "shared/log.h" 00038 #include "signer/tools.h" 00039 #include "signer/zone.h" 00040 00041 static const char* tools_str = "tools"; 00042 00043 00048 ods_status 00049 tools_input(zone_type* zone) 00050 { 00051 ods_status status = ODS_STATUS_OK; 00052 char* tmpname = NULL; 00053 char* lockname = NULL; 00054 time_t start = 0; 00055 time_t end = 0; 00056 FILE* fd = NULL; 00057 00058 if (!zone) { 00059 ods_log_error("[%s] unable to read zone: no zone", tools_str); 00060 return ODS_STATUS_ASSERT_ERR; 00061 } 00062 ods_log_assert(zone); 00063 00064 if (!zone->zonedata) { 00065 ods_log_error("[%s] unable to read zone: no zone data", tools_str); 00066 return ODS_STATUS_ASSERT_ERR; 00067 } 00068 ods_log_assert(zone->zonedata); 00069 00070 ods_log_assert(zone->adinbound); 00071 ods_log_assert(zone->signconf); 00072 00073 if (zone->stats) { 00074 lock_basic_lock(&zone->stats->stats_lock); 00075 zone->stats->sort_done = 0; 00076 zone->stats->sort_count = 0; 00077 zone->stats->sort_time = 0; 00078 lock_basic_unlock(&zone->stats->stats_lock); 00079 } 00080 00081 if (zone->adinbound->type == ADAPTER_FILE) { 00082 if (zone->fetch) { 00083 ods_log_verbose("[%s] fetch zone %s", tools_str, 00084 zone->name?zone->name:"(null)"); 00085 tmpname = ods_build_path( 00086 zone->adinbound->configstr, ".axfr", 0); 00087 lockname = ods_build_path( 00088 zone->adinbound->configstr, ".lock", 0); 00089 00090 lock_fetch: 00091 if (access(lockname, F_OK) == 0) { 00092 ods_log_deeebug("[%s] axfr file %s is locked, " 00093 "waiting...", tools_str, tmpname); 00094 sleep(1); 00095 goto lock_fetch; 00096 } else { 00097 fd = fopen(lockname, "w"); 00098 if (!fd) { 00099 ods_log_error("[%s] cannot lock AXFR file %s", 00100 tools_str, lockname); 00101 free((void*)tmpname); 00102 free((void*)lockname); 00103 return ODS_STATUS_ERR; 00104 } 00105 } 00106 ods_log_assert(fd); /* locked */ 00107 00108 status = ods_file_copy(tmpname, zone->adinbound->configstr); 00109 00110 fclose(fd); 00111 (void) unlink(lockname); /* unlocked */ 00112 00113 if (status != ODS_STATUS_OK) { 00114 ods_log_error("[%s] unable to copy axfr file %s to %s: %s", 00115 tools_str, tmpname, zone->adinbound->configstr, 00116 ods_status2str(status)); 00117 free((void*)tmpname); 00118 free((void*)lockname); 00119 return status; 00120 } 00121 free((void*)tmpname); 00122 free((void*)lockname); 00123 } 00124 } 00125 00126 start = time(NULL); 00127 status = adapter_read(zone); 00128 if (status != ODS_STATUS_OK) { 00129 ods_log_error("[%s] unable to read from input adapter for zone %s: " 00130 "%s", tools_str, zone->name?zone->name:"(null)", 00131 ods_status2str(status)); 00132 } else { 00133 tmpname = ods_build_path(zone->name, ".inbound", 0); 00134 status = ods_file_copy(zone->adinbound->configstr, tmpname); 00135 free((void*)tmpname); 00136 tmpname = NULL; 00137 if (status != ODS_STATUS_OK) { 00138 ods_log_error("[%s] unable to copy zone input file %s: %s", 00139 tools_str, zone->name?zone->name:"(null)", 00140 ods_status2str(status)); 00141 } 00142 } 00143 00144 if (status == ODS_STATUS_OK) { 00145 ods_log_verbose("[%s] commit updates for zone %s", tools_str, 00146 zone->name?zone->name:"(null)"); 00147 status = zonedata_commit(zone->zonedata); 00148 } else { 00149 ods_log_warning("[%s] rollback updates for zone %s", tools_str, 00150 zone->name?zone->name:"(null)"); 00151 zonedata_rollback(zone->zonedata); 00152 } 00153 end = time(NULL); 00154 00155 if (status == ODS_STATUS_OK && zone->stats) { 00156 lock_basic_lock(&zone->stats->stats_lock); 00157 zone->stats->start_time = start; 00158 zone->stats->sort_time = (end-start); 00159 zone->stats->sort_done = 1; 00160 lock_basic_unlock(&zone->stats->stats_lock); 00161 } 00162 return status; 00163 } 00164 00165 00170 ods_status 00171 tools_nsecify(zone_type* zone) 00172 { 00173 ods_status status = ODS_STATUS_OK; 00174 time_t start = 0; 00175 time_t end = 0; 00176 uint32_t ttl = 0; 00177 uint32_t num_added = 0; 00178 00179 if (!zone) { 00180 ods_log_error("[%s] unable to nsecify zone: no zone", tools_str); 00181 return ODS_STATUS_ASSERT_ERR; 00182 } 00183 ods_log_assert(zone); 00184 00185 if (!zone->zonedata) { 00186 ods_log_error("[%s] unable to nsecify zone %s: no zonedata", 00187 tools_str, zone->name); 00188 return ODS_STATUS_ASSERT_ERR; 00189 } 00190 ods_log_assert(zone->zonedata); 00191 00192 if (!zone->signconf) { 00193 ods_log_error("[%s] unable to nsecify zone %s: no signconf", 00194 tools_str, zone->name); 00195 return ODS_STATUS_ASSERT_ERR; 00196 } 00197 ods_log_assert(zone->signconf); 00198 00199 if (zone->stats) { 00200 lock_basic_lock(&zone->stats->stats_lock); 00201 zone->stats->nsec_time = 0; 00202 zone->stats->nsec_count = 0; 00203 lock_basic_unlock(&zone->stats->stats_lock); 00204 } 00205 00206 start = time(NULL); 00207 /* determine NSEC(3) ttl */ 00208 ttl = zone->zonedata->default_ttl; 00209 if (zone->signconf->soa_min) { 00210 ttl = (uint32_t) duration2time(zone->signconf->soa_min); 00211 } 00212 /* add missing empty non-terminals */ 00213 status = zonedata_entize(zone->zonedata, zone->dname); 00214 if (status != ODS_STATUS_OK) { 00215 ods_log_error("[%s] unable to nsecify zone %s: failed to add empty ", 00216 "non-terminals", tools_str, zone->name); 00217 return status; 00218 } 00219 00220 /* NSEC or NSEC3? */ 00221 if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC) { 00222 status = zonedata_nsecify(zone->zonedata, zone->klass, ttl, 00223 &num_added); 00224 } else if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) { 00225 if (zone->signconf->nsec3_optout) { 00226 ods_log_debug("[%s] OptOut is being used for zone %s", 00227 tools_str, zone->name); 00228 } 00229 ods_log_assert(zone->nsec3params); 00230 status = zonedata_nsecify3(zone->zonedata, zone->klass, ttl, 00231 zone->nsec3params, &num_added); 00232 } else { 00233 ods_log_error("[%s] unable to nsecify zone %s: unknown RRtype %u for ", 00234 "denial of existence", tools_str, zone->name, 00235 (unsigned) zone->signconf->nsec_type); 00236 return ODS_STATUS_ERR; 00237 } 00238 end = time(NULL); 00239 if (status == ODS_STATUS_OK && zone->stats) { 00240 lock_basic_lock(&zone->stats->stats_lock); 00241 if (!zone->stats->start_time) { 00242 zone->stats->start_time = start; 00243 } 00244 zone->stats->nsec_time = (end-start); 00245 zone->stats->nsec_count = num_added; 00246 lock_basic_unlock(&zone->stats->stats_lock); 00247 } 00248 return status; 00249 } 00250 00251 00256 ods_status 00257 tools_audit(zone_type* zone, char* working_dir, char* cfg_filename) 00258 { 00259 char* inbound = NULL; 00260 char* finalized = NULL; 00261 char str[SYSTEM_MAXLEN]; 00262 ods_status status = ODS_STATUS_OK; 00263 int error = 0; 00264 time_t start = 0; 00265 time_t end = 0; 00266 00267 if (!zone) { 00268 ods_log_error("[%s] unable to audit zone: no zone", tools_str); 00269 return ODS_STATUS_ASSERT_ERR; 00270 } 00271 ods_log_assert(zone); 00272 00273 if (!zone->signconf) { 00274 ods_log_error("[%s] unable to audit zone %s: no signconf", 00275 tools_str, zone->name?zone->name:"(null)"); 00276 return ODS_STATUS_ASSERT_ERR; 00277 } 00278 ods_log_assert(zone->signconf); 00279 00280 if (zone->stats) { 00281 lock_basic_lock(&zone->stats->stats_lock); 00282 if (zone->stats->sort_done == 0 && 00283 (zone->stats->sig_count <= zone->stats->sig_soa_count)) { 00284 lock_basic_unlock(&zone->stats->stats_lock); 00285 return ODS_STATUS_OK; 00286 } 00287 lock_basic_unlock(&zone->stats->stats_lock); 00288 } 00289 00290 if (zone->signconf->audit) { 00291 inbound = ods_build_path(zone->name, ".inbound", 0); 00292 finalized = ods_build_path(zone->name, ".finalized", 0); 00293 status = adfile_write(zone, finalized); 00294 if (status != ODS_STATUS_OK) { 00295 ods_log_error("[%s] audit zone %s failed: unable to write zone", 00296 tools_str, zone->name?zone->name:"(null)"); 00297 free((void*)inbound); 00298 free((void*)finalized); 00299 return status; 00300 } 00301 00302 snprintf(str, SYSTEM_MAXLEN, "%s -c %s -u %s/%s -s %s/%s -z %s > /dev/null", 00303 ODS_SE_AUDITOR, 00304 cfg_filename?cfg_filename:ODS_SE_CFGFILE, 00305 working_dir?working_dir:"", 00306 inbound?inbound:"(null)", 00307 working_dir?working_dir:"", 00308 finalized?finalized:"(null)", 00309 zone->name?zone->name:"(null)"); 00310 00311 start = time(NULL); 00312 ods_log_debug("system call: %s", str); 00313 error = system(str); 00314 if (finalized) { 00315 if (!error) { 00316 unlink(finalized); 00317 } 00318 free((void*)finalized); 00319 } 00320 free((void*)inbound); 00321 00322 if (error) { 00323 status = ODS_STATUS_ERR; 00324 } 00325 end = time(NULL); 00326 if (status == ODS_STATUS_OK && zone->stats) { 00327 lock_basic_lock(&zone->stats->stats_lock); 00328 zone->stats->audit_time = (end-start); 00329 lock_basic_unlock(&zone->stats->stats_lock); 00330 } 00331 } 00332 return status; 00333 } 00334 00335 00340 ods_status 00341 tools_output(zone_type* zone) 00342 { 00343 ods_status status = ODS_STATUS_OK; 00344 char str[SYSTEM_MAXLEN]; 00345 int error = 0; 00346 uint32_t outbound_serial = 0; 00347 00348 if (!zone) { 00349 ods_log_error("[%s] unable to write zone: no zone", tools_str); 00350 return ODS_STATUS_ASSERT_ERR; 00351 } 00352 ods_log_assert(zone); 00353 00354 if (!zone->adoutbound) { 00355 ods_log_error("[%s] unable to write zone %s: no outbound adapter", 00356 tools_str, zone->name?zone->name:"(null)"); 00357 return ODS_STATUS_ASSERT_ERR; 00358 } 00359 ods_log_assert(zone->adoutbound); 00360 00361 if (zone->stats) { 00362 lock_basic_lock(&zone->stats->stats_lock); 00363 if (zone->stats->sort_done == 0 && 00364 (zone->stats->sig_count <= zone->stats->sig_soa_count)) { 00365 ods_log_verbose("[%s] skip write zone %s serial %u (zone not " 00366 "changed)", tools_str, zone->name?zone->name:"(null)", 00367 zone->zonedata->internal_serial); 00368 stats_clear(zone->stats); 00369 lock_basic_unlock(&zone->stats->stats_lock); 00370 zone->zonedata->internal_serial = 00371 zone->zonedata->outbound_serial; 00372 return ODS_STATUS_OK; 00373 } 00374 lock_basic_unlock(&zone->stats->stats_lock); 00375 } 00376 00377 outbound_serial = zone->zonedata->outbound_serial; 00378 zone->zonedata->outbound_serial = zone->zonedata->internal_serial; 00379 status = adapter_write(zone); 00380 if (status != ODS_STATUS_OK) { 00381 ods_log_error("[%s] unable to write zone %s: adapter failed", 00382 tools_str, zone->name); 00383 zone->zonedata->outbound_serial = outbound_serial; 00384 return status; 00385 } 00386 00387 /* initialize zonedata */ 00388 zone->zonedata->initialized = 1; 00389 00390 /* kick the nameserver */ 00391 if (zone->notify_ns) { 00392 ods_log_verbose("[%s] notify nameserver: %s", tools_str, 00393 zone->notify_ns); 00394 snprintf(str, SYSTEM_MAXLEN, "%s > /dev/null", 00395 zone->notify_ns); 00396 error = system(str); 00397 if (error) { 00398 ods_log_error("[%s] failed to notify nameserver", tools_str); 00399 status = ODS_STATUS_ERR; 00400 } 00401 } 00402 /* log stats */ 00403 if (zone->stats) { 00404 lock_basic_lock(&zone->stats->stats_lock); 00405 zone->stats->end_time = time(NULL); 00406 ods_log_debug("[%s] log stats for zone %s", tools_str, 00407 zone->name?zone->name:"(null)"); 00408 stats_log(zone->stats, zone->name, zone->signconf->nsec_type); 00409 stats_clear(zone->stats); 00410 lock_basic_unlock(&zone->stats->stats_lock); 00411 } 00412 return status; 00413 }