OpenDNSSEC-signer
1.3.8
|
00001 /* 00002 * $Id: tools.c 6318 2012-05-09 08:56:43Z matthijs $ 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, 0); 00087 lockname = ods_build_path( 00088 zone->adinbound->configstr, ".lock", 0, 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, 1); 00134 status = ods_file_copy(zone->adinbound->configstr, tmpname); 00135 if (status != ODS_STATUS_OK) { 00136 ods_log_error("[%s] unable to copy zone input file %s: %s", 00137 tools_str, tmpname, ods_status2str(status)); 00138 } 00139 free((void*)tmpname); 00140 tmpname = NULL; 00141 } 00142 00143 if (status == ODS_STATUS_OK) { 00144 ods_log_verbose("[%s] commit updates for zone %s", tools_str, 00145 zone->name?zone->name:"(null)"); 00146 status = zonedata_commit(zone->zonedata); 00147 } else { 00148 ods_log_warning("[%s] rollback updates for zone %s", tools_str, 00149 zone->name?zone->name:"(null)"); 00150 zonedata_rollback(zone->zonedata); 00151 } 00152 end = time(NULL); 00153 00154 if (status == ODS_STATUS_OK && zone->stats) { 00155 lock_basic_lock(&zone->stats->stats_lock); 00156 zone->stats->start_time = start; 00157 zone->stats->sort_time = (end-start); 00158 zone->stats->sort_done = 1; 00159 lock_basic_unlock(&zone->stats->stats_lock); 00160 } 00161 return status; 00162 } 00163 00164 00169 ods_status 00170 tools_nsecify(zone_type* zone) 00171 { 00172 ods_status status = ODS_STATUS_OK; 00173 time_t start = 0; 00174 time_t end = 0; 00175 uint32_t ttl = 0; 00176 uint32_t num_added = 0; 00177 00178 if (!zone) { 00179 ods_log_error("[%s] unable to nsecify zone: no zone", tools_str); 00180 return ODS_STATUS_ASSERT_ERR; 00181 } 00182 ods_log_assert(zone); 00183 00184 if (!zone->zonedata) { 00185 ods_log_error("[%s] unable to nsecify zone %s: no zonedata", 00186 tools_str, zone->name); 00187 return ODS_STATUS_ASSERT_ERR; 00188 } 00189 ods_log_assert(zone->zonedata); 00190 00191 if (!zone->signconf) { 00192 ods_log_error("[%s] unable to nsecify zone %s: no signconf", 00193 tools_str, zone->name); 00194 return ODS_STATUS_ASSERT_ERR; 00195 } 00196 ods_log_assert(zone->signconf); 00197 00198 if (zone->stats) { 00199 lock_basic_lock(&zone->stats->stats_lock); 00200 zone->stats->nsec_time = 0; 00201 zone->stats->nsec_count = 0; 00202 lock_basic_unlock(&zone->stats->stats_lock); 00203 } 00204 00205 start = time(NULL); 00206 /* determine denial ttl */ 00207 ttl = zone->zonedata->default_ttl; 00208 if (zone->signconf->soa_min) { 00209 ttl = (uint32_t) duration2time(zone->signconf->soa_min); 00210 } 00211 /* add missing empty non-terminals */ 00212 status = zonedata_entize(zone->zonedata, zone->dname); 00213 if (status != ODS_STATUS_OK) { 00214 ods_log_error("[%s] unable to nsecify zone %s: failed to add empty ", 00215 "non-terminals", tools_str, zone->name); 00216 return status; 00217 } 00218 /* nsecify(3) */ 00219 if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC) { 00220 status = zonedata_nsecify(zone->zonedata, zone->klass, ttl, 00221 &num_added); 00222 } else if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) { 00223 if (zone->signconf->nsec3_optout) { 00224 ods_log_debug("[%s] OptOut is being used for zone %s", 00225 tools_str, zone->name); 00226 } 00227 ods_log_assert(zone->nsec3params); 00228 status = zonedata_nsecify3(zone->zonedata, zone->klass, ttl, 00229 zone->nsec3params, &num_added); 00230 } else { 00231 ods_log_error("[%s] unable to nsecify zone %s: unknown RRtype %u for ", 00232 "denial of existence", tools_str, zone->name, 00233 (unsigned) zone->signconf->nsec_type); 00234 return ODS_STATUS_ERR; 00235 } 00236 end = time(NULL); 00237 if (status == ODS_STATUS_OK && zone->stats) { 00238 lock_basic_lock(&zone->stats->stats_lock); 00239 if (!zone->stats->start_time) { 00240 zone->stats->start_time = start; 00241 } 00242 zone->stats->nsec_time = (end-start); 00243 zone->stats->nsec_count = num_added; 00244 lock_basic_unlock(&zone->stats->stats_lock); 00245 } 00246 return status; 00247 } 00248 00249 00254 ods_status 00255 tools_audit(zone_type* zone, char* working_dir, char* cfg_filename) 00256 { 00257 ods_status status = ODS_STATUS_OK; 00258 #ifdef HAVE_AUDITOR 00259 char* inbound = NULL; 00260 char* finalized = NULL; 00261 char str[SYSTEM_MAXLEN]; 00262 int error = 0; 00263 time_t start = 0; 00264 time_t end = 0; 00265 00266 if (!zone) { 00267 ods_log_error("[%s] unable to audit zone: no zone", tools_str); 00268 return ODS_STATUS_ASSERT_ERR; 00269 } 00270 ods_log_assert(zone); 00271 00272 if (!zone->signconf) { 00273 ods_log_error("[%s] unable to audit zone %s: no signconf", 00274 tools_str, zone->name?zone->name:"(null)"); 00275 return ODS_STATUS_ASSERT_ERR; 00276 } 00277 ods_log_assert(zone->signconf); 00278 00279 if (zone->stats) { 00280 lock_basic_lock(&zone->stats->stats_lock); 00281 if (zone->stats->sort_done == 0 && 00282 (zone->stats->sig_count <= zone->stats->sig_soa_count)) { 00283 lock_basic_unlock(&zone->stats->stats_lock); 00284 return ODS_STATUS_OK; 00285 } 00286 lock_basic_unlock(&zone->stats->stats_lock); 00287 } 00288 00289 if (zone->signconf->audit) { 00290 inbound = ods_build_path(zone->name, ".inbound", 0, 1); 00291 finalized = ods_build_path(zone->name, ".finalized", 0, 1); 00292 status = adfile_write(zone, finalized); 00293 if (status != ODS_STATUS_OK) { 00294 ods_log_error("[%s] audit zone %s failed: unable to write zone", 00295 tools_str, finalized); 00296 free((void*)inbound); 00297 free((void*)finalized); 00298 return status; 00299 } 00300 00301 snprintf(str, SYSTEM_MAXLEN, "%s -c %s -u %s/%s -s %s/%s -z %s > /dev/null", 00302 ODS_SE_AUDITOR, 00303 cfg_filename?cfg_filename:ODS_SE_CFGFILE, 00304 working_dir?working_dir:"", 00305 inbound?inbound:"(null)", 00306 working_dir?working_dir:"", 00307 finalized?finalized:"(null)", 00308 zone->name?zone->name:"(null)"); 00309 00310 start = time(NULL); 00311 ods_log_debug("system call: %s", str); 00312 error = system(str); 00313 if (finalized) { 00314 if (!error) { 00315 unlink(finalized); 00316 } 00317 free((void*)finalized); 00318 } 00319 free((void*)inbound); 00320 00321 if (error) { 00322 ods_log_error("[%s] audit failed for zone %s", tools_str, 00323 zone->name); 00324 status = ODS_STATUS_ERR; 00325 } else { 00326 ods_log_info("[%s] audit passed for zone %s", tools_str, 00327 zone->name); 00328 } 00329 end = time(NULL); 00330 if (status == ODS_STATUS_OK && zone->stats) { 00331 lock_basic_lock(&zone->stats->stats_lock); 00332 zone->stats->audit_time = (end-start); 00333 lock_basic_unlock(&zone->stats->stats_lock); 00334 } 00335 } 00336 #else 00337 ods_log_error("[%s] unable to audit zone %s: ods-auditor not installed", 00338 tools_str, zone->name?zone->name:"(null)"); 00339 status = ODS_STATUS_ERR; 00340 #endif 00341 return status; 00342 } 00343 00344 00349 ods_status 00350 tools_output(zone_type* zone) 00351 { 00352 ods_status status = ODS_STATUS_OK; 00353 char str[SYSTEM_MAXLEN]; 00354 int error = 0; 00355 uint32_t outbound_serial = 0; 00356 00357 if (!zone) { 00358 ods_log_error("[%s] unable to write zone: no zone", tools_str); 00359 return ODS_STATUS_ASSERT_ERR; 00360 } 00361 ods_log_assert(zone); 00362 00363 if (!zone->adoutbound) { 00364 ods_log_error("[%s] unable to write zone %s: no outbound adapter", 00365 tools_str, zone->name?zone->name:"(null)"); 00366 return ODS_STATUS_ASSERT_ERR; 00367 } 00368 ods_log_assert(zone->adoutbound); 00369 00370 if (zone->stats) { 00371 lock_basic_lock(&zone->stats->stats_lock); 00372 if (zone->stats->sort_done == 0 && 00373 (zone->stats->sig_count <= zone->stats->sig_soa_count)) { 00374 ods_log_verbose("[%s] skip write zone %s serial %u (zone not " 00375 "changed)", tools_str, zone->name?zone->name:"(null)", 00376 zone->zonedata->internal_serial); 00377 stats_clear(zone->stats); 00378 lock_basic_unlock(&zone->stats->stats_lock); 00379 zone->zonedata->internal_serial = 00380 zone->zonedata->outbound_serial; 00381 return ODS_STATUS_OK; 00382 } 00383 lock_basic_unlock(&zone->stats->stats_lock); 00384 } 00385 00386 outbound_serial = zone->zonedata->outbound_serial; 00387 zone->zonedata->outbound_serial = zone->zonedata->internal_serial; 00388 status = adapter_write(zone); 00389 if (status != ODS_STATUS_OK) { 00390 ods_log_error("[%s] unable to write zone %s: adapter failed (%s)", 00391 tools_str, zone->name, ods_status2str(status)); 00392 zone->zonedata->outbound_serial = outbound_serial; 00393 return status; 00394 } 00395 00396 /* initialize zonedata */ 00397 zone->zonedata->initialized = 1; 00398 00399 /* kick the nameserver */ 00400 if (zone->notify_ns) { 00401 ods_log_verbose("[%s] notify nameserver: %s", tools_str, 00402 zone->notify_ns); 00403 snprintf(str, SYSTEM_MAXLEN, "%s > /dev/null", 00404 zone->notify_ns); 00405 error = system(str); 00406 if (error) { 00407 ods_log_error("[%s] failed to notify nameserver", tools_str); 00408 status = ODS_STATUS_ERR; 00409 } 00410 } 00411 /* log stats */ 00412 if (zone->stats) { 00413 lock_basic_lock(&zone->stats->stats_lock); 00414 zone->stats->end_time = time(NULL); 00415 ods_log_debug("[%s] log stats for zone %s", tools_str, 00416 zone->name?zone->name:"(null)"); 00417 stats_log(zone->stats, zone->name, zone->signconf->nsec_type); 00418 stats_clear(zone->stats); 00419 lock_basic_unlock(&zone->stats->stats_lock); 00420 } 00421 return status; 00422 }