OpenDNSSEC-signer  1.3.16
tools.c
Go to the documentation of this file.
1 /*
2  * $Id: tools.c 7295 2013-09-11 10:18:25Z matthijs $
3  *
4  * Copyright (c) 2009 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "config.h"
35 #include "adapter/adapter.h"
36 #include "shared/file.h"
37 #include "shared/log.h"
38 #include "signer/tools.h"
39 #include "signer/zone.h"
40 
41 static const char* tools_str = "tools";
42 
43 
50 {
51  ods_status status = ODS_STATUS_OK;
52  char* tmpname = NULL;
53  char* lockname = NULL;
54  time_t start = 0;
55  time_t end = 0;
56  FILE* fd = NULL;
57 
58  if (!zone) {
59  ods_log_error("[%s] unable to read zone: no zone", tools_str);
60  return ODS_STATUS_ASSERT_ERR;
61  }
62  ods_log_assert(zone);
63 
64  if (!zone->zonedata) {
65  ods_log_error("[%s] unable to read zone: no zone data", tools_str);
66  return ODS_STATUS_ASSERT_ERR;
67  }
68  ods_log_assert(zone->zonedata);
69 
71  ods_log_assert(zone->signconf);
72 
73  if (zone->stats) {
76  zone->stats->sort_done = 0;
77  zone->stats->sort_count = 0;
78  zone->stats->sort_time = 0;
79  zone->stats->stats_locked = 0;
81  }
82 
83  if (zone->adinbound->type == ADAPTER_FILE) {
84  if (zone->fetch) {
85  ods_log_verbose("[%s] fetch zone %s", tools_str,
86  zone->name?zone->name:"(null)");
87  tmpname = ods_build_path(
88  zone->adinbound->configstr, ".axfr", 0, 0);
89  lockname = ods_build_path(
90  zone->adinbound->configstr, ".lock", 0, 0);
91 
92 lock_fetch:
93  if (access(lockname, F_OK) == 0) {
94  ods_log_deeebug("[%s] axfr file %s is locked, "
95  "waiting...", tools_str, tmpname);
96  sleep(1);
97  goto lock_fetch;
98  } else {
99  fd = fopen(lockname, "w");
100  if (!fd) {
101  ods_log_error("[%s] cannot lock AXFR file %s",
102  tools_str, lockname);
103  free((void*)tmpname);
104  free((void*)lockname);
105  return ODS_STATUS_ERR;
106  }
107  }
108  ods_log_assert(fd); /* locked */
109 
110  status = ods_file_copy(tmpname, zone->adinbound->configstr);
111 
112  fclose(fd);
113  (void) unlink(lockname); /* unlocked */
114 
115  if (status != ODS_STATUS_OK) {
116  ods_log_error("[%s] unable to copy axfr file %s to %s: %s",
117  tools_str, tmpname, zone->adinbound->configstr,
118  ods_status2str(status));
119  free((void*)tmpname);
120  free((void*)lockname);
121  return status;
122  }
123  free((void*)tmpname);
124  free((void*)lockname);
125  }
126  }
127 
128  start = time(NULL);
129  status = adapter_read(zone);
130  if (status != ODS_STATUS_OK) {
131  ods_log_error("[%s] unable to read from input adapter for zone %s: "
132  "%s", tools_str, zone->name?zone->name:"(null)",
133  ods_status2str(status));
134  } else {
135  tmpname = ods_build_path(zone->name, ".inbound", 0, 1);
136  status = ods_file_copy(zone->adinbound->configstr, tmpname);
137  if (status != ODS_STATUS_OK) {
138  ods_log_error("[%s] unable to copy zone input file %s: %s",
139  tools_str, tmpname, ods_status2str(status));
140  }
141  free((void*)tmpname);
142  tmpname = NULL;
143  }
144 
145  if (status == ODS_STATUS_OK) {
146  ods_log_verbose("[%s] commit updates for zone %s", tools_str,
147  zone->name?zone->name:"(null)");
148  status = zonedata_commit(zone->zonedata);
149  } else {
150  ods_log_warning("[%s] rollback updates for zone %s", tools_str,
151  zone->name?zone->name:"(null)");
153  }
154  end = time(NULL);
155 
156  if (status == ODS_STATUS_OK && zone->stats) {
159  zone->stats->start_time = start;
160  zone->stats->sort_time = (end-start);
161  zone->stats->sort_done = 1;
162  zone->stats->stats_locked = 0;
164  }
165  return status;
166 }
167 
168 
175 {
176  ods_status status = ODS_STATUS_OK;
177  time_t start = 0;
178  time_t end = 0;
179  uint32_t ttl = 0;
180  uint32_t num_added = 0;
181 
182  if (!zone) {
183  ods_log_error("[%s] unable to nsecify zone: no zone", tools_str);
184  return ODS_STATUS_ASSERT_ERR;
185  }
186  ods_log_assert(zone);
187 
188  if (!zone->zonedata) {
189  ods_log_error("[%s] unable to nsecify zone %s: no zonedata",
190  tools_str, zone->name);
191  return ODS_STATUS_ASSERT_ERR;
192  }
193  ods_log_assert(zone->zonedata);
194 
195  if (!zone->signconf) {
196  ods_log_error("[%s] unable to nsecify zone %s: no signconf",
197  tools_str, zone->name);
198  return ODS_STATUS_ASSERT_ERR;
199  }
200  ods_log_assert(zone->signconf);
201 
202  if (zone->stats) {
205  zone->stats->nsec_time = 0;
206  zone->stats->nsec_count = 0;
207  zone->stats->stats_locked = 0;
209  }
210 
211  start = time(NULL);
212  /* determine denial ttl */
213  ttl = zone->zonedata->default_ttl;
214  if (zone->signconf->soa_min) {
215  ttl = (uint32_t) duration2time(zone->signconf->soa_min);
216  }
217  /* add missing empty non-terminals */
218  status = zonedata_entize(zone->zonedata, zone->dname);
219  if (status != ODS_STATUS_OK) {
220  ods_log_error("[%s] unable to nsecify zone %s: failed to add empty ",
221  "non-terminals", tools_str, zone->name);
222  return status;
223  }
224  /* nsecify(3) */
225  if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC) {
226  status = zonedata_nsecify(zone->zonedata, zone->klass, ttl,
227  &num_added);
228  } else if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) {
229  if (zone->signconf->nsec3_optout) {
230  ods_log_debug("[%s] OptOut is being used for zone %s",
231  tools_str, zone->name);
232  }
234  status = zonedata_nsecify3(zone->zonedata, zone->klass, ttl,
235  zone->nsec3params, &num_added);
236  } else {
237  ods_log_error("[%s] unable to nsecify zone %s: unknown RRtype %u for ",
238  "denial of existence", tools_str, zone->name,
239  (unsigned) zone->signconf->nsec_type);
240  return ODS_STATUS_ERR;
241  }
242  end = time(NULL);
243  if (status == ODS_STATUS_OK && zone->stats) {
246  if (!zone->stats->start_time) {
247  zone->stats->start_time = start;
248  }
249  zone->stats->nsec_time = (end-start);
250  zone->stats->nsec_count = num_added;
251  zone->stats->stats_locked = 0;
253  }
254  return status;
255 }
256 
257 
263 tools_audit(zone_type* zone, char* working_dir, char* cfg_filename)
264 {
265  ods_status status = ODS_STATUS_OK;
266 #ifdef HAVE_AUDITOR
267  char* inbound = NULL;
268  char* finalized = NULL;
269  char str[SYSTEM_MAXLEN];
270  int error = 0;
271  time_t start = 0;
272  time_t end = 0;
273 
274  if (!zone) {
275  ods_log_error("[%s] unable to audit zone: no zone", tools_str);
276  return ODS_STATUS_ASSERT_ERR;
277  }
278  ods_log_assert(zone);
279 
280  if (!zone->signconf) {
281  ods_log_error("[%s] unable to audit zone %s: no signconf",
282  tools_str, zone->name?zone->name:"(null)");
283  return ODS_STATUS_ASSERT_ERR;
284  }
285  ods_log_assert(zone->signconf);
286 
287  if (zone->stats) {
290  if (zone->stats->sort_done == 0 &&
291  (zone->stats->sig_count <= zone->stats->sig_soa_count)) {
293  return ODS_STATUS_OK;
294  }
295  zone->stats->stats_locked = 0;
297  }
298 
299  if (zone->signconf->audit) {
300  inbound = ods_build_path(zone->name, ".inbound", 0, 1);
301  finalized = ods_build_path(zone->name, ".finalized", 0, 1);
302  status = adfile_write(zone, finalized);
303  if (status != ODS_STATUS_OK) {
304  ods_log_error("[%s] audit zone %s failed: unable to write zone",
305  tools_str, finalized);
306  free((void*)inbound);
307  free((void*)finalized);
308  return status;
309  }
310 
311  snprintf(str, SYSTEM_MAXLEN, "%s -c %s -u %s/%s -s %s/%s -z %s > /dev/null",
312  ODS_SE_AUDITOR,
313  cfg_filename?cfg_filename:ODS_SE_CFGFILE,
314  working_dir?working_dir:"",
315  inbound?inbound:"(null)",
316  working_dir?working_dir:"",
317  finalized?finalized:"(null)",
318  zone->name?zone->name:"(null)");
319 
320  start = time(NULL);
321  ods_log_debug("system call: %s", str);
322  error = system(str);
323  if (finalized) {
324  if (!error) {
325  unlink(finalized);
326  }
327  free((void*)finalized);
328  }
329  free((void*)inbound);
330 
331  if (error) {
332  ods_log_error("[%s] audit failed for zone %s", tools_str,
333  zone->name);
334  status = ODS_STATUS_ERR;
335  } else {
336  ods_log_info("[%s] audit passed for zone %s", tools_str,
337  zone->name);
338  }
339  end = time(NULL);
340  if (status == ODS_STATUS_OK && zone->stats) {
343  zone->stats->audit_time = (end-start);
344  zone->stats->stats_locked = 0;
346  }
347  }
348 #else
349  ods_log_error("[%s] unable to audit zone %s: ods-auditor not installed",
350  tools_str, zone->name?zone->name:"(null)");
351  status = ODS_STATUS_ERR;
352 #endif
353  return status;
354 }
355 
356 
363 {
364  ods_status status = ODS_STATUS_OK;
365  char str[SYSTEM_MAXLEN];
366  int error = 0;
367  uint32_t outbound_serial = 0;
368 
369  if (!zone) {
370  ods_log_error("[%s] unable to write zone: no zone", tools_str);
371  return ODS_STATUS_ASSERT_ERR;
372  }
373  ods_log_assert(zone);
374 
375  if (!zone->adoutbound) {
376  ods_log_error("[%s] unable to write zone %s: no outbound adapter",
377  tools_str, zone->name?zone->name:"(null)");
378  return ODS_STATUS_ASSERT_ERR;
379  }
380  ods_log_assert(zone->adoutbound);
381 
382  if (zone->stats) {
385  if (zone->stats->sort_done == 0 &&
386  (zone->stats->sig_count <= zone->stats->sig_soa_count)) {
387  ods_log_verbose("[%s] skip write zone %s serial %u (zone not "
388  "changed)", tools_str, zone->name?zone->name:"(null)",
389  zone->zonedata->internal_serial);
390  stats_clear(zone->stats);
391  zone->stats->stats_locked = 0;
393  zone->zonedata->internal_serial =
394  zone->zonedata->outbound_serial;
395  return ODS_STATUS_OK;
396  }
397  zone->stats->stats_locked = 0;
399  }
400 
401  outbound_serial = zone->zonedata->outbound_serial;
403  status = adapter_write(zone);
404  if (status != ODS_STATUS_OK) {
405  ods_log_error("[%s] unable to write zone %s: adapter failed (%s)",
406  tools_str, zone->name, ods_status2str(status));
407  zone->zonedata->outbound_serial = outbound_serial;
408  return status;
409  }
410 
411  /* initialize zonedata */
412  zone->zonedata->initialized = 1;
413 
414  /* kick the nameserver */
415  if (zone->notify_ns) {
416  ods_log_verbose("[%s] notify nameserver: %s", tools_str,
417  zone->notify_ns);
418  snprintf(str, SYSTEM_MAXLEN, "%s > /dev/null",
419  zone->notify_ns);
420  error = system(str);
421  if (error) {
422  ods_log_error("[%s] failed to notify nameserver", tools_str);
423  status = ODS_STATUS_ERR;
424  }
425  }
426  /* log stats */
427  if (zone->stats) {
430  zone->stats->end_time = time(NULL);
431  ods_log_debug("[%s] log stats for zone %s", tools_str,
432  zone->name?zone->name:"(null)");
433  stats_log(zone->stats, zone->name, zone->signconf->nsec_type);
434  stats_clear(zone->stats);
435  zone->stats->stats_locked = 0;
437  }
438  return status;
439 }
uint32_t outbound_serial
Definition: zonedata.h:68
int sort_done
Definition: stats.h:59
#define LOCKED_STATS_TOOLS_OUTPUT_START
Definition: locks.h:72
#define LOCKED_STATS_TOOLS_AUDIT_STOP
Definition: locks.h:71
void ods_log_debug(const char *format,...)
Definition: log.c:285
duration_type * soa_min
Definition: signconf.h:74
uint32_t internal_serial
Definition: zonedata.h:67
ods_status zonedata_entize(zonedata_type *zd, ldns_rdf *apex)
Definition: zonedata.c:913
void stats_log(stats_type *stats, const char *name, ldns_rr_type nsec_type)
Definition: stats.c:80
int fetch
Definition: zone.h:64
const char * configstr
Definition: adapter.h:65
time_t audit_time
Definition: stats.h:66
void ods_log_info(const char *format,...)
Definition: log.c:317
enum ods_enum_status ods_status
Definition: status.h:64
#define LOCKED_STATS_TOOLS_NSECIFY_STOP
Definition: locks.h:69
ldns_rdf * dname
Definition: zone.h:59
ods_status tools_audit(zone_type *zone, char *working_dir, char *cfg_filename)
Definition: tools.c:263
void ods_log_error(const char *format,...)
Definition: log.c:349
lock_basic_type stats_lock
Definition: stats.h:69
#define LOCKED_STATS_TOOLS_INPUT_START
Definition: locks.h:66
const char * ods_status2str(ods_status status)
Definition: status.c:84
#define LOCKED_STATS_TOOLS_NSECIFY_START
Definition: locks.h:68
adapter_mode type
Definition: adapter.h:66
#define LOCKED_STATS_TOOLS_INPUT_STOP
Definition: locks.h:67
nsec3params_type * nsec3params
Definition: zone.h:82
void zonedata_rollback(zonedata_type *zd)
Definition: zonedata.c:739
ldns_rr_type nsec_type
Definition: signconf.h:64
time_t nsec_time
Definition: stats.h:61
adapter_type * adoutbound
Definition: zone.h:78
uint32_t nsec_count
Definition: stats.h:60
ods_status zonedata_nsecify(zonedata_type *zd, ldns_rr_class klass, uint32_t ttl, uint32_t *num_added)
Definition: zonedata.c:955
ods_status tools_input(zone_type *zone)
Definition: tools.c:49
#define lock_basic_lock(lock)
Definition: locks.h:154
ods_status adapter_read(struct zone_struct *zone)
Definition: adapter.c:114
#define SYSTEM_MAXLEN
Definition: file.h:51
signconf_type * signconf
Definition: zone.h:81
time_t start_time
Definition: stats.h:67
time_t sort_time
Definition: stats.h:58
adapter_type * adinbound
Definition: zone.h:77
ods_status adapter_write(struct zone_struct *zone)
Definition: adapter.c:152
uint32_t default_ttl
Definition: zonedata.h:65
time_t end_time
Definition: stats.h:68
#define LOCKED_STATS_TOOLS_LOG
Definition: locks.h:74
char * ods_build_path(const char *file, const char *suffix, int dir, int no_slash)
Definition: file.c:128
const char * notify_ns
Definition: zone.h:63
time_t duration2time(duration_type *duration)
Definition: duration.c:340
void ods_log_verbose(const char *format,...)
Definition: log.c:301
ldns_rr_class klass
Definition: zone.h:60
#define LOCKED_STATS_TOOLS_AUDIT_START
Definition: locks.h:70
ods_status tools_output(zone_type *zone)
Definition: tools.c:362
uint32_t sort_count
Definition: stats.h:57
const char * name
Definition: zone.h:67
ods_status zonedata_commit(zonedata_type *zd)
Definition: zonedata.c:687
uint32_t sig_soa_count
Definition: stats.h:63
void ods_log_deeebug(const char *format,...)
Definition: log.c:269
uint32_t sig_count
Definition: stats.h:62
int stats_locked
Definition: stats.h:70
ods_status tools_nsecify(zone_type *zone)
Definition: tools.c:174
ods_status zonedata_nsecify3(zonedata_type *zd, ldns_rr_class klass, uint32_t ttl, nsec3params_type *nsec3params, uint32_t *num_added)
Definition: zonedata.c:1048
zonedata_type * zonedata
Definition: zone.h:85
#define ods_log_assert(x)
Definition: log.h:141
ods_status adfile_write(struct zone_struct *zone, const char *filename)
Definition: adfile.c:430
#define lock_basic_unlock(lock)
Definition: locks.h:155
void ods_log_warning(const char *format,...)
Definition: log.c:333
ods_status ods_file_copy(const char *file1, const char *file2)
Definition: file.c:396
stats_type * stats
Definition: zone.h:91
void stats_clear(stats_type *stats)
Definition: stats.c:57
int nsec3_optout
Definition: signconf.h:65