dnssec.c 2.92 KB
Newer Older
1
/*  Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <assert.h>
#include <urcu.h>

#include "knot/common/log.h"
#include "knot/conf/conf.h"
#include "knot/dnssec/zone-events.h"
23
#include "knot/events/log.h"
24 25 26 27
#include "knot/updates/apply.h"
#include "knot/zone/zone.h"
#include "libknot/errcode.h"

28 29
void event_dnssec_reschedule(conf_t *conf, zone_t *zone,
			     const zone_sign_reschedule_t *refresh, bool zone_changed)
30
{
31 32
	time_t now = time(NULL);
	time_t ignore = -1;
33
	knot_time_t refresh_at = refresh->next_sign;
34

35
	if (knot_time_cmp(refresh->next_rollover, refresh_at) < 0) {
36 37
		refresh_at = refresh->next_rollover;
	}
38

39 40 41 42 43
	if (refresh_at <= 0) {
		return;
	}

	log_dnssec_next(zone->name, (time_t)refresh_at);
44 45

	if (refresh->plan_ds_query) {
46
		log_zone_notice(zone->name, "DNSSEC, KSK submission, waiting for confirmation");
47
		zone->timers.next_parent_ds_q = now;
48 49
	}

50 51 52 53
	if (refresh->allow_nsec3resalt) {
		zone->timers.last_resalt = time(NULL);
	}

54
	zone_events_schedule_at(zone,
55
		ZONE_EVENT_DNSSEC, (time_t)refresh_at,
56
		ZONE_EVENT_PARENT_DS_Q, refresh->plan_ds_query ? now : ignore,
57
		ZONE_EVENT_NSEC3RESALT, refresh->next_nsec3resalt ? refresh->next_nsec3resalt : ignore,
58
		ZONE_EVENT_NOTIFY, zone_changed ? now : ignore
59
	);
60 61 62 63 64 65
}

int event_dnssec(conf_t *conf, zone_t *zone)
{
	assert(zone);

66 67
	zone_sign_reschedule_t resch = { 0 };
	resch.allow_rollover = true;
68 69 70 71
	int sign_flags = 0;

	if (zone->flags & ZONE_FORCE_RESIGN) {
		log_zone_info(zone->name, "DNSSEC, dropping previous "
72
		              "signatures, re-signing zone");
73 74 75 76 77 78 79
		zone->flags &= ~ZONE_FORCE_RESIGN;
		sign_flags = ZONE_SIGN_DROP_SIGNATURES;
	} else {
		log_zone_info(zone->name, "DNSSEC, signing zone");
		sign_flags = 0;
	}

80 81 82 83
	if (zone_events_get_time(zone, ZONE_EVENT_NSEC3RESALT) <= time(NULL)) {
		resch.allow_nsec3resalt = true;
	}

84 85 86 87 88 89 90
	zone_update_t up;
	int ret = zone_update_init(&up, zone, UPDATE_INCREMENTAL);
	if (ret != KNOT_EOK) {
		return ret;
	}

	ret = knot_dnssec_zone_sign(&up, sign_flags, &resch);
91 92 93 94
	if (ret != KNOT_EOK) {
		goto done;
	}

95
	bool zone_changed = !zone_update_no_change(&up);
96
	if (zone_changed) {
97
		ret = zone_update_commit(conf, &up);
98 99 100 101 102
		if (ret != KNOT_EOK) {
			goto done;
		}
	}

103
	// Schedule dependent events
104
	event_dnssec_reschedule(conf, zone, &resch, zone_changed);
105 106

done:
107
	zone_update_clear(&up);
108 109
	return ret;
}