OpenDNSSEC-signer
1.3.4
|
00001 /* 00002 * $Id: tools.c 5849 2011-11-14 08:43:44Z 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); 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 denial 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 /* nsecify(3) */ 00220 if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC) { 00221 status = zonedata_nsecify(zone->zonedata, zone->klass, ttl, 00222 &num_added); 00223 } else if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) { 00224 if (zone->signconf->nsec3_optout) { 00225 ods_log_debug("[%s] OptOut is being used for zone %s", 00226 tools_str, zone->name); 00227 } 00228 ods_log_assert(zone->nsec3params); 00229 status = zonedata_nsecify3(zone->zonedata, zone->klass, ttl, 00230 zone->nsec3params, &num_added); 00231 } else { 00232 ods_log_error("[%s] unable to nsecify zone %s: unknown RRtype %u for ", 00233 "denial of existence", tools_str, zone->name, 00234 (unsigned) zone->signconf->nsec_type); 00235 return ODS_STATUS_ERR; 00236 } 00237 end = time(NULL); 00238 if (status == ODS_STATUS_OK && zone->stats) { 00239 lock_basic_lock(&zone->stats->stats_lock); 00240 if (!zone->stats->start_time) { 00241 zone->stats->start_time = start; 00242 } 00243 zone->stats->nsec_time = (end-start); 00244 zone->stats->nsec_count = num_added; 00245 lock_basic_unlock(&zone->stats->stats_lock); 00246 } 00247 return status; 00248 } 00249 00250 00255 ods_status 00256 tools_audit(zone_type* zone, char* working_dir, char* cfg_filename) 00257 { 00258 char* inbound = NULL; 00259 char* finalized = NULL; 00260 char str[SYSTEM_MAXLEN]; 00261 ods_status status = ODS_STATUS_OK; 00262 int error = 0; 00263 time_t start = 0; 00264 time_t end = 0; 00265 if (!zone) { 00266 ods_log_error("[%s] unable to audit zone: no zone", tools_str); 00267 return ODS_STATUS_ASSERT_ERR; 00268 } 00269 ods_log_assert(zone); 00270 00271 if (!zone->signconf) { 00272 ods_log_error("[%s] unable to audit zone %s: no signconf", 00273 tools_str, zone->name?zone->name:"(null)"); 00274 return ODS_STATUS_ASSERT_ERR; 00275 } 00276 ods_log_assert(zone->signconf); 00277 00278 if (zone->stats) { 00279 lock_basic_lock(&zone->stats->stats_lock); 00280 if (zone->stats->sort_done == 0 && 00281 (zone->stats->sig_count <= zone->stats->sig_soa_count)) { 00282 lock_basic_unlock(&zone->stats->stats_lock); 00283 return ODS_STATUS_OK; 00284 } 00285 lock_basic_unlock(&zone->stats->stats_lock); 00286 } 00287 00288 if (zone->signconf->audit) { 00289 inbound = ods_build_path(zone->name, ".inbound", 0); 00290 finalized = ods_build_path(zone->name, ".finalized", 0); 00291 status = adfile_write(zone, finalized); 00292 if (status != ODS_STATUS_OK) { 00293 ods_log_error("[%s] audit zone %s failed: unable to write zone", 00294 tools_str, zone->name?zone->name:"(null)"); 00295 free((void*)inbound); 00296 free((void*)finalized); 00297 return status; 00298 } 00299 00300 snprintf(str, SYSTEM_MAXLEN, "%s -c %s -u %s/%s -s %s/%s -z %s > /dev/null", 00301 ODS_SE_AUDITOR, 00302 cfg_filename?cfg_filename:ODS_SE_CFGFILE, 00303 working_dir?working_dir:"", 00304 inbound?inbound:"(null)", 00305 working_dir?working_dir:"", 00306 finalized?finalized:"(null)", 00307 zone->name?zone->name:"(null)"); 00308 00309 start = time(NULL); 00310 ods_log_debug("system call: %s", str); 00311 error = system(str); 00312 if (finalized) { 00313 if (!error) { 00314 unlink(finalized); 00315 } 00316 free((void*)finalized); 00317 } 00318 free((void*)inbound); 00319 00320 if (error) { 00321 ods_log_error("[%s] audit failed for zone %s", tools_str, 00322 zone->name); 00323 status = ODS_STATUS_ERR; 00324 } else { 00325 ods_log_info("[%s] audit passed for zone %s", tools_str, 00326 zone->name); 00327 } 00328 end = time(NULL); 00329 if (status == ODS_STATUS_OK && zone->stats) { 00330 lock_basic_lock(&zone->stats->stats_lock); 00331 zone->stats->audit_time = (end-start); 00332 lock_basic_unlock(&zone->stats->stats_lock); 00333 } 00334 } 00335 return status; 00336 } 00337 00338 00343 ods_status 00344 tools_output(zone_type* zone) 00345 { 00346 ods_status status = ODS_STATUS_OK; 00347 char str[SYSTEM_MAXLEN]; 00348 int error = 0; 00349 uint32_t outbound_serial = 0; 00350 00351 if (!zone) { 00352 ods_log_error("[%s] unable to write zone: no zone", tools_str); 00353 return ODS_STATUS_ASSERT_ERR; 00354 } 00355 ods_log_assert(zone); 00356 00357 if (!zone->adoutbound) { 00358 ods_log_error("[%s] unable to write zone %s: no outbound adapter", 00359 tools_str, zone->name?zone->name:"(null)"); 00360 return ODS_STATUS_ASSERT_ERR; 00361 } 00362 ods_log_assert(zone->adoutbound); 00363 00364 if (zone->stats) { 00365 lock_basic_lock(&zone->stats->stats_lock); 00366 if (zone->stats->sort_done == 0 && 00367 (zone->stats->sig_count <= zone->stats->sig_soa_count)) { 00368 ods_log_verbose("[%s] skip write zone %s serial %u (zone not " 00369 "changed)", tools_str, zone->name?zone->name:"(null)", 00370 zone->zonedata->internal_serial); 00371 stats_clear(zone->stats); 00372 lock_basic_unlock(&zone->stats->stats_lock); 00373 zone->zonedata->internal_serial = 00374 zone->zonedata->outbound_serial; 00375 return ODS_STATUS_OK; 00376 } 00377 lock_basic_unlock(&zone->stats->stats_lock); 00378 } 00379 00380 outbound_serial = zone->zonedata->outbound_serial; 00381 zone->zonedata->outbound_serial = zone->zonedata->internal_serial; 00382 status = adapter_write(zone); 00383 if (status != ODS_STATUS_OK) { 00384 ods_log_error("[%s] unable to write zone %s: adapter failed", 00385 tools_str, zone->name); 00386 zone->zonedata->outbound_serial = outbound_serial; 00387 return status; 00388 } 00389 00390 /* initialize zonedata */ 00391 zone->zonedata->initialized = 1; 00392 00393 /* kick the nameserver */ 00394 if (zone->notify_ns) { 00395 ods_log_verbose("[%s] notify nameserver: %s", tools_str, 00396 zone->notify_ns); 00397 snprintf(str, SYSTEM_MAXLEN, "%s > /dev/null", 00398 zone->notify_ns); 00399 error = system(str); 00400 if (error) { 00401 ods_log_error("[%s] failed to notify nameserver", tools_str); 00402 status = ODS_STATUS_ERR; 00403 } 00404 } 00405 /* log stats */ 00406 if (zone->stats) { 00407 lock_basic_lock(&zone->stats->stats_lock); 00408 zone->stats->end_time = time(NULL); 00409 ods_log_debug("[%s] log stats for zone %s", tools_str, 00410 zone->name?zone->name:"(null)"); 00411 stats_log(zone->stats, zone->name, zone->signconf->nsec_type); 00412 stats_clear(zone->stats); 00413 lock_basic_unlock(&zone->stats->stats_lock); 00414 } 00415 return status; 00416 }