mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
autotrust state table updates.
git-svn-id: file:///svn/unbound/trunk@1767 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
701b4ccdd6
commit
0deef63323
6 changed files with 505 additions and 101 deletions
|
|
@ -1,3 +1,6 @@
|
||||||
|
19 August 2009: Wouter
|
||||||
|
- autotrust: state table updates.
|
||||||
|
|
||||||
17 August 2009: Wouter
|
17 August 2009: Wouter
|
||||||
- autotrust: process events.
|
- autotrust: process events.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -491,6 +491,13 @@ File with trusted keys for validation. Both DS and DNSKEY entries can appear
|
||||||
in the file. The format of the file is the standard DNS Zone file format.
|
in the file. The format of the file is the standard DNS Zone file format.
|
||||||
Default is "", or no trust anchor file.
|
Default is "", or no trust anchor file.
|
||||||
.TP
|
.TP
|
||||||
|
.B auto\-trust\-anchor\-file: \fI<filename>
|
||||||
|
File with trust anchor for one zone, which is tracked with RFC5011 probes.
|
||||||
|
The probes are several times per month, thus the machine must be online
|
||||||
|
frequently. The initial file can be one with contents as described in
|
||||||
|
\fBtrust\-anchor\-file\fR. The file is written to when the anchor is updated,
|
||||||
|
so the unbound user must have write permission.
|
||||||
|
.TP
|
||||||
.B trust\-anchor: \fI<"Resource Record">
|
.B trust\-anchor: \fI<"Resource Record">
|
||||||
A DS or DNSKEY RR for a key to use for validation. Multiple entries can be
|
A DS or DNSKEY RR for a key to use for validation. Multiple entries can be
|
||||||
given to specify multiple trusted keys, in addition to the trust\-anchor\-files.
|
given to specify multiple trusted keys, in addition to the trust\-anchor\-files.
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,9 @@ config_create()
|
||||||
cfg->val_clean_additional = 1;
|
cfg->val_clean_additional = 1;
|
||||||
cfg->val_log_level = 0;
|
cfg->val_log_level = 0;
|
||||||
cfg->val_permissive_mode = 0;
|
cfg->val_permissive_mode = 0;
|
||||||
|
cfg->add_holddown = 30*24*3600;
|
||||||
|
cfg->del_holddown = 30*24*3600;
|
||||||
|
cfg->keep_missing = 366*24*3600; /* one year plus a little leeway */
|
||||||
cfg->key_cache_size = 4 * 1024 * 1024;
|
cfg->key_cache_size = 4 * 1024 * 1024;
|
||||||
cfg->key_cache_slabs = 4;
|
cfg->key_cache_slabs = 4;
|
||||||
cfg->neg_cache_size = 1 * 1024 * 1024;
|
cfg->neg_cache_size = 1 * 1024 * 1024;
|
||||||
|
|
|
||||||
|
|
@ -221,6 +221,12 @@ struct config_file {
|
||||||
int val_permissive_mode;
|
int val_permissive_mode;
|
||||||
/** nsec3 maximum iterations per key size, string */
|
/** nsec3 maximum iterations per key size, string */
|
||||||
char* val_nsec3_key_iterations;
|
char* val_nsec3_key_iterations;
|
||||||
|
/** autotrust add holddown time, in seconds */
|
||||||
|
unsigned int add_holddown;
|
||||||
|
/** autotrust del holddown time, in seconds */
|
||||||
|
unsigned int del_holddown;
|
||||||
|
/** autotrust keep_missing time, in seconds. 0 is forever. */
|
||||||
|
unsigned int keep_missing;
|
||||||
|
|
||||||
/** size of the key cache */
|
/** size of the key cache */
|
||||||
size_t key_cache_size;
|
size_t key_cache_size;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
*
|
*
|
||||||
* Contains autotrust implementation.
|
* Contains autotrust implementation. The implementation was taken from
|
||||||
|
* the autotrust daemon (BSD licensed), written by Matthijs Mekking.
|
||||||
*/
|
*/
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "validator/autotrust.h"
|
#include "validator/autotrust.h"
|
||||||
|
|
@ -48,6 +49,10 @@
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
#include "util/module.h"
|
#include "util/module.h"
|
||||||
#include "util/net_help.h"
|
#include "util/net_help.h"
|
||||||
|
#include "util/config_file.h"
|
||||||
|
|
||||||
|
/** number of times a key must be seen before it can become valid */
|
||||||
|
#define MIN_PENDINGCOUNT 2
|
||||||
|
|
||||||
struct autr_global_data* autr_global_create(void)
|
struct autr_global_data* autr_global_create(void)
|
||||||
{
|
{
|
||||||
|
|
@ -109,6 +114,35 @@ position_in_string(char *str, const char* sub)
|
||||||
return pos + (int)strlen(sub);
|
return pos + (int)strlen(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Debug routine to print pretty key information */
|
||||||
|
static void
|
||||||
|
verbose_key(struct autr_ta* ta, enum verbosity_value level,
|
||||||
|
const char* format, ...) ATTR_FORMAT(printf, 3, 4);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of debug pretty key print
|
||||||
|
* @param ta: trust anchor key with DNSKEY data.
|
||||||
|
* @param level: verbosity level to print at.
|
||||||
|
* @param format: printf style format string.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
verbose_key(struct autr_ta* ta, enum verbosity_value level,
|
||||||
|
const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
if(verbosity >= level) {
|
||||||
|
char* str = ldns_rdf2str(ldns_rr_owner(ta->rr));
|
||||||
|
int keytag = (int)ldns_calc_keytag(ta->rr);
|
||||||
|
char msg[MAXSYSLOGMSGLEN];
|
||||||
|
vsnprintf(msg, sizeof(msg), format, args);
|
||||||
|
verbose(level, "autotrust %s key %d %s", str?str:"??",
|
||||||
|
keytag, msg);
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse comments
|
* Parse comments
|
||||||
* @param str: to parse
|
* @param str: to parse
|
||||||
|
|
@ -154,8 +188,6 @@ parse_comments(char* str, struct autr_ta* ta)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int s = (int) comments[pos] - '0';
|
int s = (int) comments[pos] - '0';
|
||||||
char* str = ldns_rdf2str(ldns_rr_owner(ta->rr));
|
|
||||||
|
|
||||||
switch(s)
|
switch(s)
|
||||||
{
|
{
|
||||||
case AUTR_STATE_START:
|
case AUTR_STATE_START:
|
||||||
|
|
@ -167,14 +199,11 @@ parse_comments(char* str, struct autr_ta* ta)
|
||||||
ta->s = s;
|
ta->s = s;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_warn("trust anchor [%s, DNSKEY, id=%i] has "
|
verbose_key(ta, VERB_OPS, "has undefined "
|
||||||
"undefined state, considered NewKey",
|
"state, considered NewKey");
|
||||||
str, ldns_calc_keytag(ta->rr));
|
|
||||||
ta->s = AUTR_STATE_START;
|
ta->s = AUTR_STATE_START;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(str);
|
|
||||||
}
|
}
|
||||||
/* read pending count */
|
/* read pending count */
|
||||||
pos = position_in_string(comments, "count=");
|
pos = position_in_string(comments, "count=");
|
||||||
|
|
@ -208,11 +237,8 @@ parse_comments(char* str, struct autr_ta* ta)
|
||||||
if (pos < 0 || !timestamp)
|
if (pos < 0 || !timestamp)
|
||||||
{
|
{
|
||||||
/* Should we warn about this? It happens for key priming.
|
/* Should we warn about this? It happens for key priming.
|
||||||
ldns_rdf* owner = ldns_rr_owner(ta->rr);
|
verbose_key(ta, VERB_OPS, "has no timestamp, "
|
||||||
char* str = ldns_rdf2str(owner);
|
"considered NOW");
|
||||||
log_warn("trust anchor [%s, DNSKEY, id=%i] has no timestamp, "
|
|
||||||
"considered NOW", str, ldns_calc_keytag(ta->rr));
|
|
||||||
free(str);
|
|
||||||
*/
|
*/
|
||||||
/* cannot use event base timeptr, because not inited yet */
|
/* cannot use event base timeptr, because not inited yet */
|
||||||
ta->last_change = (uint32_t)time(NULL);
|
ta->last_change = (uint32_t)time(NULL);
|
||||||
|
|
@ -310,29 +336,33 @@ autr_tp_create(struct val_anchors* anchors, ldns_rr* rr)
|
||||||
|
|
||||||
/** delete assembled rrsets */
|
/** delete assembled rrsets */
|
||||||
static void
|
static void
|
||||||
autr_rrset_delete(struct trust_anchor* tp)
|
autr_rrset_delete(struct ub_packed_rrset_key* r)
|
||||||
{
|
{
|
||||||
if(tp->ds_rrset) {
|
if(r) {
|
||||||
free(tp->ds_rrset->rk.dname);
|
free(r->rk.dname);
|
||||||
free(tp->ds_rrset->entry.data);
|
free(r->entry.data);
|
||||||
free(tp->ds_rrset);
|
free(r);
|
||||||
}
|
|
||||||
if(tp->dnskey_rrset) {
|
|
||||||
free(tp->dnskey_rrset->rk.dname);
|
|
||||||
free(tp->dnskey_rrset->entry.data);
|
|
||||||
free(tp->dnskey_rrset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void autr_point_delete(struct trust_anchor* tp)
|
void autr_point_delete(struct trust_anchor* tp)
|
||||||
{
|
{
|
||||||
|
struct autr_ta* p, *np;
|
||||||
if(!tp)
|
if(!tp)
|
||||||
return;
|
return;
|
||||||
lock_unprotect(&tp->lock, tp);
|
lock_unprotect(&tp->lock, tp);
|
||||||
lock_unprotect(&tp->lock, tp->autr);
|
lock_unprotect(&tp->lock, tp->autr);
|
||||||
lock_basic_destroy(&tp->lock);
|
lock_basic_destroy(&tp->lock);
|
||||||
autr_rrset_delete(tp);
|
autr_rrset_delete(tp->ds_rrset);
|
||||||
|
autr_rrset_delete(tp->dnskey_rrset);
|
||||||
|
p = tp->autr->keys;
|
||||||
|
while(p) {
|
||||||
|
np = p->next;
|
||||||
|
ldns_rr_free(p->rr);
|
||||||
|
free(p);
|
||||||
|
p = np;
|
||||||
|
}
|
||||||
free(tp->autr);
|
free(tp->autr);
|
||||||
free(tp->name);
|
free(tp->name);
|
||||||
free(tp);
|
free(tp);
|
||||||
|
|
@ -424,12 +454,6 @@ load_trustanchor(struct val_anchors* anchors, char* str, const char* fname)
|
||||||
lock_basic_unlock(&tp->lock);
|
lock_basic_unlock(&tp->lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (rr_is_dnskey_sep(ta->rr)) {
|
|
||||||
if (ta->s == AUTR_STATE_VALID)
|
|
||||||
tp->autr->valid ++;
|
|
||||||
else if (ta->s == AUTR_STATE_MISSING)
|
|
||||||
tp->autr->missing ++;
|
|
||||||
}
|
|
||||||
if(!tp->autr->file) {
|
if(!tp->autr->file) {
|
||||||
/* TODO insert tp into probe tree */
|
/* TODO insert tp into probe tree */
|
||||||
tp->autr->file = strdup(fname);
|
tp->autr->file = strdup(fname);
|
||||||
|
|
@ -444,6 +468,7 @@ load_trustanchor(struct val_anchors* anchors, char* str, const char* fname)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assemble the trust anchors into DS and DNSKEY packed rrsets.
|
* Assemble the trust anchors into DS and DNSKEY packed rrsets.
|
||||||
|
* Uses only VALID and MISSING DNSKEYs.
|
||||||
* Read the ldns_rrs and builds packed rrsets
|
* Read the ldns_rrs and builds packed rrsets
|
||||||
* @param tp: the trust point. Must be locked.
|
* @param tp: the trust point. Must be locked.
|
||||||
* @return false on malloc failure.
|
* @return false on malloc failure.
|
||||||
|
|
@ -469,7 +494,8 @@ autr_assemble(struct trust_anchor* tp)
|
||||||
ldns_rr_list_free(dnskey);
|
ldns_rr_list_free(dnskey);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else if(ta->s == AUTR_STATE_VALID ||
|
||||||
|
ta->s == AUTR_STATE_MISSING) {
|
||||||
if(!ldns_rr_list_push_rr(dnskey, ta->rr)) {
|
if(!ldns_rr_list_push_rr(dnskey, ta->rr)) {
|
||||||
ldns_rr_list_free(ds);
|
ldns_rr_list_free(ds);
|
||||||
ldns_rr_list_free(dnskey);
|
ldns_rr_list_free(dnskey);
|
||||||
|
|
@ -496,16 +522,8 @@ autr_assemble(struct trust_anchor* tp)
|
||||||
ubdnskey->entry.data = packed_rrset_heap_data(dnskey);
|
ubdnskey->entry.data = packed_rrset_heap_data(dnskey);
|
||||||
if(!ubdnskey->entry.data) {
|
if(!ubdnskey->entry.data) {
|
||||||
error_cleanup:
|
error_cleanup:
|
||||||
if(ubds) {
|
autr_rrset_delete(ubds);
|
||||||
free(ubds->rk.dname);
|
autr_rrset_delete(ubdnskey);
|
||||||
free(ubds->entry.data);
|
|
||||||
free(ubds);
|
|
||||||
}
|
|
||||||
if(ubdnskey) {
|
|
||||||
free(ubdnskey->rk.dname);
|
|
||||||
free(ubdnskey->entry.data);
|
|
||||||
free(ubdnskey);
|
|
||||||
}
|
|
||||||
ldns_rr_list_free(ds);
|
ldns_rr_list_free(ds);
|
||||||
ldns_rr_list_free(dnskey);
|
ldns_rr_list_free(dnskey);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -513,7 +531,8 @@ autr_assemble(struct trust_anchor* tp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free the old data */
|
/* free the old data */
|
||||||
autr_rrset_delete(tp);
|
autr_rrset_delete(tp->ds_rrset);
|
||||||
|
autr_rrset_delete(tp->dnskey_rrset);
|
||||||
|
|
||||||
/* assign the data to replace the old */
|
/* assign the data to replace the old */
|
||||||
tp->ds_rrset = ubds;
|
tp->ds_rrset = ubds;
|
||||||
|
|
@ -540,7 +559,7 @@ int autr_read_file(struct val_anchors* anchors, const char* nm)
|
||||||
nm, strerror(errno));
|
nm, strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
verbose(VERB_ALGO, "reading trust anchor file %s", nm);
|
verbose(VERB_ALGO, "reading autotrust anchor file %s", nm);
|
||||||
/* TODO: read line to see if special marker for revoked tp */
|
/* TODO: read line to see if special marker for revoked tp */
|
||||||
/* TODO: read next probe time (if in file, otherwise now+0-100s) */
|
/* TODO: read next probe time (if in file, otherwise now+0-100s) */
|
||||||
while (fgets(line, (int)sizeof(line), fd) != NULL) {
|
while (fgets(line, (int)sizeof(line), fd) != NULL) {
|
||||||
|
|
@ -568,18 +587,59 @@ int autr_read_file(struct val_anchors* anchors, const char* nm)
|
||||||
|
|
||||||
/* now assemble the data into DNSKEY and DS packed rrsets */
|
/* now assemble the data into DNSKEY and DS packed rrsets */
|
||||||
lock_basic_lock(&tp->lock);
|
lock_basic_lock(&tp->lock);
|
||||||
autr_assemble(tp);
|
if(!autr_assemble(tp)) {
|
||||||
|
lock_basic_unlock(&tp->lock);
|
||||||
|
log_err("malloc failure assembling %s", nm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
lock_basic_unlock(&tp->lock);
|
lock_basic_unlock(&tp->lock);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void autr_write_file(struct trust_anchor* tp)
|
void autr_write_file(struct trust_anchor* tp)
|
||||||
{
|
{
|
||||||
|
char tmi[32];
|
||||||
|
FILE* out;
|
||||||
|
struct autr_ta* ta;
|
||||||
|
log_assert(tp->autr);
|
||||||
|
out = fopen(tp->autr->file, "w");
|
||||||
|
if(!out) {
|
||||||
|
log_err("Could not open autotrust file for writing, %s: %s",
|
||||||
|
tp->autr->file, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
/* write pretty header */
|
/* write pretty header */
|
||||||
|
fprintf(out, "; autotrust trust anchor file\n");
|
||||||
|
|
||||||
/* write revoked tp special marker */
|
/* write revoked tp special marker */
|
||||||
/* write next probe time */
|
/* write next probe time */
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
/* write anchors */
|
/* write anchors */
|
||||||
|
for(ta=tp->autr->keys; ta; ta=ta->next) {
|
||||||
|
char* str;
|
||||||
|
|
||||||
|
/* by default do not store START and REMOVED keys */
|
||||||
|
if(ta->s == AUTR_STATE_START)
|
||||||
|
continue;
|
||||||
|
if(ta->s == AUTR_STATE_REMOVED)
|
||||||
|
continue;
|
||||||
|
/* only store SEP keys */
|
||||||
|
if(!rr_is_dnskey_sep(ta->rr))
|
||||||
|
continue;
|
||||||
|
str = ldns_rr2str(ta->rr);
|
||||||
|
if(!str || !str[0]) {
|
||||||
|
log_err("malloc failure writing %s", tp->autr->file);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
str[strlen(str)-1] = 0;
|
||||||
|
ctime_r(&(ta->last_change), tmi);
|
||||||
|
fprintf(out, "%s ;;state=%d ;;count=%d ;;lastchange=%u ;;%s",
|
||||||
|
str, (int)ta->s, (int)ta->pending_count,
|
||||||
|
(unsigned int)ta->last_change, tmi);
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
fclose(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** verify if dnskey works for trust point
|
/** verify if dnskey works for trust point
|
||||||
|
|
@ -618,7 +678,7 @@ verify_dnskey(struct module_env* env, struct val_env* ve,
|
||||||
|
|
||||||
/** Find minimum expiration interval from signatures */
|
/** Find minimum expiration interval from signatures */
|
||||||
static uint32_t
|
static uint32_t
|
||||||
rrsig_min_exp_time(struct module_env* env, ldns_rr_list* rrset)
|
min_expiry(struct module_env* env, ldns_rr_list* rrset)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
uint32_t t, r = 15 * 24 * 3600; /* 15 days max */
|
uint32_t t, r = 15 * 24 * 3600; /* 15 days max */
|
||||||
|
|
@ -661,7 +721,26 @@ seen_revoked_trustanchor(struct autr_ta* ta, uint8_t revoked)
|
||||||
ta->revoked = revoked;
|
ta->revoked = revoked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare two RR buffers, skipping the REVOKED bit */
|
/** revoke a trust anchor */
|
||||||
|
static void
|
||||||
|
revoke_dnskey(struct autr_ta* ta, int off)
|
||||||
|
{
|
||||||
|
ldns_rdf* rdf;
|
||||||
|
uint16_t flags;
|
||||||
|
log_assert(ta && ta->rr);
|
||||||
|
if(!ldns_rr_get_type(ta->rr) != LDNS_RR_TYPE_DNSKEY)
|
||||||
|
return;
|
||||||
|
rdf = ldns_rr_dnskey_flags(ta->rr);
|
||||||
|
flags = ldns_read_uint16(ldns_rdf_data(rdf));
|
||||||
|
|
||||||
|
if (off && (flags&LDNS_KEY_REVOKE_KEY))
|
||||||
|
flags ^= LDNS_KEY_REVOKE_KEY; /* flip */
|
||||||
|
else
|
||||||
|
flags |= LDNS_KEY_REVOKE_KEY;
|
||||||
|
ldns_write_uint16(ldns_rdf_data(rdf), flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compare two RR buffers skipping the REVOKED bit */
|
||||||
static int
|
static int
|
||||||
ldns_rr_compare_wire_skip_revbit(ldns_buffer* rr1_buf, ldns_buffer* rr2_buf)
|
ldns_rr_compare_wire_skip_revbit(ldns_buffer* rr1_buf, ldns_buffer* rr2_buf)
|
||||||
{
|
{
|
||||||
|
|
@ -695,15 +774,14 @@ ldns_rr_compare_wire_skip_revbit(ldns_buffer* rr1_buf, ldns_buffer* rr2_buf)
|
||||||
|
|
||||||
/** Compare two RRs skipping the REVOKED bit */
|
/** Compare two RRs skipping the REVOKED bit */
|
||||||
static int
|
static int
|
||||||
ldns_rr_compare_skip_revbit(const ldns_rr* rr1, const ldns_rr* rr2)
|
ldns_rr_compare_skip_revbit(const ldns_rr* rr1, const ldns_rr* rr2, int* result)
|
||||||
{
|
{
|
||||||
int result;
|
|
||||||
size_t rr1_len, rr2_len;
|
size_t rr1_len, rr2_len;
|
||||||
ldns_buffer* rr1_buf;
|
ldns_buffer* rr1_buf;
|
||||||
ldns_buffer* rr2_buf;
|
ldns_buffer* rr2_buf;
|
||||||
|
|
||||||
result = ldns_rr_compare_no_rdata(rr1, rr2);
|
*result = ldns_rr_compare_no_rdata(rr1, rr2);
|
||||||
if (result == 0)
|
if (*result == 0)
|
||||||
{
|
{
|
||||||
rr1_len = ldns_rr_uncompressed_size(rr1);
|
rr1_len = ldns_rr_uncompressed_size(rr1);
|
||||||
rr2_len = ldns_rr_uncompressed_size(rr2);
|
rr2_len = ldns_rr_uncompressed_size(rr2);
|
||||||
|
|
@ -727,44 +805,57 @@ ldns_rr_compare_skip_revbit(const ldns_rr* rr1, const ldns_rr* rr2)
|
||||||
ldns_buffer_free(rr2_buf);
|
ldns_buffer_free(rr2_buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
result = ldns_rr_compare_wire_skip_revbit(rr1_buf, rr2_buf);
|
*result = ldns_rr_compare_wire_skip_revbit(rr1_buf, rr2_buf);
|
||||||
ldns_buffer_free(rr1_buf);
|
ldns_buffer_free(rr1_buf);
|
||||||
ldns_buffer_free(rr2_buf);
|
ldns_buffer_free(rr2_buf);
|
||||||
}
|
}
|
||||||
return result;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** compare two trust anchors */
|
/** compare two trust anchors */
|
||||||
static int
|
static int
|
||||||
ta_compare(ldns_rr* a, ldns_rr* b)
|
ta_compare(ldns_rr* a, ldns_rr* b, int* result)
|
||||||
{
|
{
|
||||||
int result;
|
if (!a && !b) *result = 0;
|
||||||
if (!a && !b) result = 0;
|
else if (!a) *result = -1;
|
||||||
else if (!a) result = -1;
|
else if (!b) *result = 1;
|
||||||
else if (!b) result = 1;
|
|
||||||
else if (ldns_rr_get_type(a) != ldns_rr_get_type(b))
|
else if (ldns_rr_get_type(a) != ldns_rr_get_type(b))
|
||||||
result = (int)ldns_rr_get_type(a) - (int)ldns_rr_get_type(b);
|
*result = (int)ldns_rr_get_type(a) - (int)ldns_rr_get_type(b);
|
||||||
else if (ldns_rr_get_type(a) == LDNS_RR_TYPE_DNSKEY)
|
else if (ldns_rr_get_type(a) == LDNS_RR_TYPE_DNSKEY) {
|
||||||
result = ldns_rr_compare_skip_revbit(a, b);
|
if(!ldns_rr_compare_skip_revbit(a, b, result))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
else if (ldns_rr_get_type(a) == LDNS_RR_TYPE_DS)
|
else if (ldns_rr_get_type(a) == LDNS_RR_TYPE_DS)
|
||||||
result = ldns_rr_compare(a, b);
|
*result = ldns_rr_compare(a, b);
|
||||||
else result = -1;
|
else *result = -1;
|
||||||
return result;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** find key */
|
/**
|
||||||
static struct autr_ta*
|
* Find key
|
||||||
find_key(struct trust_anchor* tp, ldns_rr* rr)
|
* @param tp: to search in
|
||||||
|
* @param rr: to look for
|
||||||
|
* @param result: returns NULL or the ta key looked for.
|
||||||
|
* @return false on malloc failure during search. if true examine result.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
find_key(struct trust_anchor* tp, ldns_rr* rr, struct autr_ta** result)
|
||||||
{
|
{
|
||||||
struct autr_ta* ta;
|
struct autr_ta* ta;
|
||||||
|
int ret;
|
||||||
if(!tp || !rr)
|
if(!tp || !rr)
|
||||||
return NULL;
|
return 0;
|
||||||
for(ta=tp->autr->keys; ta; ta=ta->next) {
|
for(ta=tp->autr->keys; ta; ta=ta->next) {
|
||||||
if(ta_compare(ta->rr, rr) == 0)
|
if(!ta_compare(ta->rr, rr, &ret))
|
||||||
return ta;
|
return 0;
|
||||||
|
if(ret == 0) {
|
||||||
|
*result = ta;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
return NULL;
|
}
|
||||||
|
*result = NULL;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** add key and clone RR and tp already locked */
|
/** add key and clone RR and tp already locked */
|
||||||
|
|
@ -786,14 +877,21 @@ add_key(struct trust_anchor* tp, ldns_rr* rr)
|
||||||
return ta;
|
return ta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** get TTL from DNSKEY rrset */
|
||||||
|
static uint32_t
|
||||||
|
key_ttl(struct ub_packed_rrset_key* k)
|
||||||
|
{
|
||||||
|
struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
|
||||||
|
return d->ttl;
|
||||||
|
}
|
||||||
|
|
||||||
/** update the time values for the trustpoint */
|
/** update the time values for the trustpoint */
|
||||||
static void
|
static void
|
||||||
set_tp_times(struct trust_anchor* tp, uint32_t rrsig_exp_interval,
|
set_tp_times(struct trust_anchor* tp, uint32_t rrsig_exp_interval,
|
||||||
struct ub_packed_rrset_key* k)
|
uint32_t origttl, int* changed)
|
||||||
{
|
{
|
||||||
struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
|
|
||||||
uint32_t origttl = d->ttl;
|
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
|
uint32_t qi = tp->autr->query_interval, rt = tp->autr->retry_time;
|
||||||
|
|
||||||
verbose(VERB_ALGO, "orig_ttl is %d", (int)origttl);
|
verbose(VERB_ALGO, "orig_ttl is %d", (int)origttl);
|
||||||
verbose(VERB_ALGO, "rrsig_exp_interval is %d", (int)rrsig_exp_interval);
|
verbose(VERB_ALGO, "rrsig_exp_interval is %d", (int)rrsig_exp_interval);
|
||||||
|
|
@ -820,6 +918,9 @@ set_tp_times(struct trust_anchor* tp, uint32_t rrsig_exp_interval,
|
||||||
tp->autr->retry_time = 3600;
|
tp->autr->retry_time = 3600;
|
||||||
else tp->autr->retry_time = x;
|
else tp->autr->retry_time = x;
|
||||||
|
|
||||||
|
if(qi != tp->autr->query_interval || rt != tp->autr->retry_time)
|
||||||
|
*changed = 1;
|
||||||
|
|
||||||
verbose(VERB_ALGO, "query_interval: %d, retry_time: %d",
|
verbose(VERB_ALGO, "query_interval: %d, retry_time: %d",
|
||||||
(int)tp->autr->query_interval, (int)tp->autr->retry_time);
|
(int)tp->autr->query_interval, (int)tp->autr->retry_time);
|
||||||
}
|
}
|
||||||
|
|
@ -837,7 +938,8 @@ init_events(struct trust_anchor* tp)
|
||||||
/** Set update events */
|
/** Set update events */
|
||||||
static int
|
static int
|
||||||
update_events(struct module_env* env, struct val_env* ve,
|
update_events(struct module_env* env, struct val_env* ve,
|
||||||
struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset)
|
struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset,
|
||||||
|
int* changed)
|
||||||
{
|
{
|
||||||
ldns_rr_list* r = packed_rrset_to_rr_list(dnskey_rrset,
|
ldns_rr_list* r = packed_rrset_to_rr_list(dnskey_rrset,
|
||||||
env->scratch_buffer);
|
env->scratch_buffer);
|
||||||
|
|
@ -853,9 +955,14 @@ update_events(struct module_env* env, struct val_env* ve,
|
||||||
if(!rr_is_dnskey_sep(rr))
|
if(!rr_is_dnskey_sep(rr))
|
||||||
continue;
|
continue;
|
||||||
/* is it new? if revocation bit set, find the unrevoked key */
|
/* is it new? if revocation bit set, find the unrevoked key */
|
||||||
ta = find_key(tp, rr);
|
if(!find_key(tp, rr, &ta)) {
|
||||||
if(!ta)
|
ldns_rr_list_deep_free(r); /* malloc fail in compare*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!ta) {
|
||||||
ta = add_key(tp, rr);
|
ta = add_key(tp, rr);
|
||||||
|
*changed = 1;
|
||||||
|
}
|
||||||
if(!ta) {
|
if(!ta) {
|
||||||
ldns_rr_list_deep_free(r);
|
ldns_rr_list_deep_free(r);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -865,31 +972,290 @@ update_events(struct module_env* env, struct val_env* ve,
|
||||||
/* checked if there is an rrsig signed by this key. */
|
/* checked if there is an rrsig signed by this key. */
|
||||||
log_assert(dnskey_calc_keytag(dnskey_rrset, i) ==
|
log_assert(dnskey_calc_keytag(dnskey_rrset, i) ==
|
||||||
ldns_calc_keytag(rr));
|
ldns_calc_keytag(rr));
|
||||||
if(verbosity >= VERB_ALGO)
|
verbose_key(ta, VERB_ALGO, "is self-signed revoked");
|
||||||
verbose(VERB_ALGO, "DNSKEY id=%d is "
|
if(!ta->revoked)
|
||||||
"self-signed revoked", (int)
|
*changed = 1;
|
||||||
dnskey_calc_keytag(dnskey_rrset, i));
|
|
||||||
seen_revoked_trustanchor(ta, 1);
|
seen_revoked_trustanchor(ta, 1);
|
||||||
} else {
|
} else {
|
||||||
seen_trustanchor(ta, 1);
|
seen_trustanchor(ta, 1);
|
||||||
if(verbosity >= VERB_ALGO)
|
verbose_key(ta, VERB_ALGO, "in DNS response");
|
||||||
verbose(VERB_ALGO, "DNSKEY id=%d in DNS "
|
|
||||||
"response", (int)ldns_calc_keytag(rr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_tp_times(tp, rrsig_min_exp_time(env, r), dnskey_rrset);
|
set_tp_times(tp, min_expiry(env, r), key_ttl(dnskey_rrset), changed);
|
||||||
ldns_rr_list_deep_free(r);
|
ldns_rr_list_deep_free(r);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** string for a trustanchor state */
|
||||||
|
static const char*
|
||||||
|
trustanchor_state2str(autr_state_t s)
|
||||||
|
{
|
||||||
|
switch (s) {
|
||||||
|
case AUTR_STATE_START: return " START ";
|
||||||
|
case AUTR_STATE_ADDPEND: return " ADDPEND ";
|
||||||
|
case AUTR_STATE_VALID: return " VALID ";
|
||||||
|
case AUTR_STATE_MISSING: return " MISSING ";
|
||||||
|
case AUTR_STATE_REVOKED: return " REVOKED ";
|
||||||
|
case AUTR_STATE_REMOVED: return " REMOVED ";
|
||||||
|
}
|
||||||
|
return " UNKNOWN ";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the holddown time has already exceeded
|
||||||
|
* setting: add-holddown: add holddown timer
|
||||||
|
* setting: del-holddown: del holddown timer
|
||||||
|
* @param env: environment with current time
|
||||||
|
* @param ta: trust anchor to check for.
|
||||||
|
* @param holddown: the timer value
|
||||||
|
* @return number of seconds the holddown has passed.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
check_holddown(struct module_env* env, struct autr_ta* ta,
|
||||||
|
unsigned int holddown)
|
||||||
|
{
|
||||||
|
unsigned int elapsed = (unsigned int)( *env->now - ta->last_change );
|
||||||
|
if (elapsed > holddown) {
|
||||||
|
return (int) (elapsed-holddown);
|
||||||
|
}
|
||||||
|
verbose_key(ta, VERB_ALGO, "holddown time %d seconds to go",
|
||||||
|
(int) (holddown-elapsed));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Set last_change to now */
|
||||||
|
static void
|
||||||
|
reset_holddown(struct module_env* env, struct autr_ta* ta, int* changed)
|
||||||
|
{
|
||||||
|
ta->last_change = *env->now;
|
||||||
|
*changed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the state for this trust anchor */
|
||||||
|
static void
|
||||||
|
set_trustanchor_state(struct module_env* env, struct autr_ta* ta, int* changed,
|
||||||
|
autr_state_t s)
|
||||||
|
{
|
||||||
|
verbose_key(ta, VERB_ALGO, "update: %s to %s",
|
||||||
|
trustanchor_state2str(ta->s), trustanchor_state2str(s));
|
||||||
|
ta->s = s;
|
||||||
|
reset_holddown(env, ta, changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Event: NewKey */
|
||||||
|
static void
|
||||||
|
do_newkey(struct module_env* env, struct autr_ta* anchor, int* c)
|
||||||
|
{
|
||||||
|
if (anchor->s == AUTR_STATE_START)
|
||||||
|
set_trustanchor_state(env, anchor, c, AUTR_STATE_ADDPEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Event: AddTime */
|
||||||
|
static void
|
||||||
|
do_addtime(struct module_env* env, struct autr_ta* anchor, int* c)
|
||||||
|
{
|
||||||
|
int exceeded = check_holddown(env, anchor, env->cfg->add_holddown);
|
||||||
|
if (exceeded && anchor->s == AUTR_STATE_ADDPEND) {
|
||||||
|
verbose_key(anchor, VERB_ALGO, "add-holddown time exceeded "
|
||||||
|
"%d seconds ago", exceeded);
|
||||||
|
if(anchor->pending_count >= MIN_PENDINGCOUNT) {
|
||||||
|
set_trustanchor_state(env, anchor, c, AUTR_STATE_VALID);
|
||||||
|
anchor->pending_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
verbose_key(anchor, VERB_ALGO, "add-holddown time sanity check "
|
||||||
|
"failed (pending count: %d)", anchor->pending_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Event: RemTime */
|
||||||
|
static void
|
||||||
|
do_remtime(struct module_env* env, struct autr_ta* anchor, int* c)
|
||||||
|
{
|
||||||
|
int exceeded = check_holddown(env, anchor, env->cfg->del_holddown);
|
||||||
|
if(exceeded && anchor->s == AUTR_STATE_REVOKED) {
|
||||||
|
verbose_key(anchor, VERB_ALGO, "del-holddown time exceeded "
|
||||||
|
"%d seconds ago", exceeded);
|
||||||
|
set_trustanchor_state(env, anchor, c, AUTR_STATE_REMOVED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Event: KeyRem */
|
||||||
|
static void
|
||||||
|
do_keyrem(struct module_env* env, struct autr_ta* anchor, int* c)
|
||||||
|
{
|
||||||
|
if(anchor->s == AUTR_STATE_ADDPEND) {
|
||||||
|
set_trustanchor_state(env, anchor, c, AUTR_STATE_START);
|
||||||
|
anchor->pending_count = 0;
|
||||||
|
} else if(anchor->s == AUTR_STATE_VALID)
|
||||||
|
set_trustanchor_state(env, anchor, c, AUTR_STATE_MISSING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Event: KeyPres */
|
||||||
|
static void
|
||||||
|
do_keypres(struct module_env* env, struct autr_ta* anchor, int* c)
|
||||||
|
{
|
||||||
|
if(anchor->s == AUTR_STATE_MISSING)
|
||||||
|
set_trustanchor_state(env, anchor, c, AUTR_STATE_VALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Event: Revoked */
|
||||||
|
static void
|
||||||
|
do_revoked(struct module_env* env, struct autr_ta* anchor, int* c)
|
||||||
|
{
|
||||||
|
if(anchor->s == AUTR_STATE_VALID || anchor->s == AUTR_STATE_MISSING) {
|
||||||
|
set_trustanchor_state(env, anchor, c, AUTR_STATE_REVOKED);
|
||||||
|
verbose_key(anchor, VERB_ALGO, "old id, prior to revocation");
|
||||||
|
revoke_dnskey(anchor, 0);
|
||||||
|
verbose_key(anchor, VERB_ALGO, "new id, after revocation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Do statestable transition matrix for anchor */
|
||||||
|
static void
|
||||||
|
anchor_state_update(struct module_env* env, struct autr_ta* anchor, int* c)
|
||||||
|
{
|
||||||
|
log_assert(anchor);
|
||||||
|
switch(anchor->s) {
|
||||||
|
/* START */
|
||||||
|
case AUTR_STATE_START:
|
||||||
|
/* NewKey: ADDPEND */
|
||||||
|
if (anchor->fetched)
|
||||||
|
do_newkey(env, anchor, c);
|
||||||
|
break;
|
||||||
|
/* ADDPEND */
|
||||||
|
case AUTR_STATE_ADDPEND:
|
||||||
|
/* KeyRem: START */
|
||||||
|
if (!anchor->fetched)
|
||||||
|
do_keyrem(env, anchor, c);
|
||||||
|
/* AddTime: VALID */
|
||||||
|
else do_addtime(env, anchor, c);
|
||||||
|
break;
|
||||||
|
/* VALID */
|
||||||
|
case AUTR_STATE_VALID:
|
||||||
|
/* RevBit: REVOKED */
|
||||||
|
if (anchor->revoked)
|
||||||
|
do_revoked(env, anchor, c);
|
||||||
|
/* KeyRem: MISSING */
|
||||||
|
else if (!anchor->fetched)
|
||||||
|
do_keyrem(env, anchor, c);
|
||||||
|
break;
|
||||||
|
/* MISSING */
|
||||||
|
case AUTR_STATE_MISSING:
|
||||||
|
/* RevBit: REVOKED */
|
||||||
|
if (anchor->revoked)
|
||||||
|
do_revoked(env, anchor, c);
|
||||||
|
/* KeyPres */
|
||||||
|
else if (anchor->fetched)
|
||||||
|
do_keypres(env, anchor, c);
|
||||||
|
break;
|
||||||
|
/* REVOKED */
|
||||||
|
case AUTR_STATE_REVOKED:
|
||||||
|
if (anchor->fetched)
|
||||||
|
reset_holddown(env, anchor, c);
|
||||||
|
/* RemTime: REMOVED */
|
||||||
|
else do_remtime(env, anchor, c);
|
||||||
|
break;
|
||||||
|
/* REMOVED */
|
||||||
|
case AUTR_STATE_REMOVED:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove missing trustanchors so the list does not grow forever */
|
||||||
|
static void
|
||||||
|
remove_missing_trustanchors(struct module_env* env, struct trust_anchor* tp,
|
||||||
|
int* changed)
|
||||||
|
{
|
||||||
|
struct autr_ta* anchor;
|
||||||
|
int exceeded;
|
||||||
|
int valid = 0;
|
||||||
|
if(env->cfg->keep_missing == 0)
|
||||||
|
return; /* keep forever */
|
||||||
|
/* see if we have anchors that are valid */
|
||||||
|
for(anchor = tp->autr->keys; anchor; anchor = anchor->next) {
|
||||||
|
/* Only do KSKs */
|
||||||
|
if (!rr_is_dnskey_sep(anchor->rr))
|
||||||
|
continue;
|
||||||
|
if (anchor->s != AUTR_STATE_VALID)
|
||||||
|
valid++;
|
||||||
|
}
|
||||||
|
if(valid == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(anchor = tp->autr->keys; anchor; anchor = anchor->next) {
|
||||||
|
/* Only do KSKs */
|
||||||
|
if (!rr_is_dnskey_sep(anchor->rr))
|
||||||
|
continue;
|
||||||
|
/* Only do MISSING keys */
|
||||||
|
if (anchor->s != AUTR_STATE_MISSING)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
exceeded = check_holddown(env, anchor, env->cfg->keep_missing);
|
||||||
|
/* If keep_missing has exceeded and we still have more than
|
||||||
|
* one valid KSK: remove missing trust anchor */
|
||||||
|
if (exceeded && valid > 0) {
|
||||||
|
verbose_key(anchor, VERB_ALGO, "keep-missing time "
|
||||||
|
"exceeded %d seconds ago, [%d keys VALID]",
|
||||||
|
exceeded, valid);
|
||||||
|
set_trustanchor_state(env, anchor, changed,
|
||||||
|
AUTR_STATE_REMOVED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Do the statetable from RFC5011 transition matrix */
|
||||||
|
static int
|
||||||
|
do_statetable(struct module_env* env, struct trust_anchor* tp, int* changed)
|
||||||
|
{
|
||||||
|
struct autr_ta* anchor;
|
||||||
|
for(anchor = tp->autr->keys; anchor; anchor = anchor->next) {
|
||||||
|
/* Only do KSKs */
|
||||||
|
if(!rr_is_dnskey_sep(anchor->rr))
|
||||||
|
continue;
|
||||||
|
anchor_state_update(env, anchor, changed);
|
||||||
|
}
|
||||||
|
remove_missing_trustanchors(env, tp, changed);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** cleanup key list */
|
||||||
|
static void
|
||||||
|
autr_cleanup_keys(struct trust_anchor* tp)
|
||||||
|
{
|
||||||
|
struct autr_ta* p, **prevp;
|
||||||
|
p = tp->autr->keys;
|
||||||
|
prevp = &tp->autr->keys;
|
||||||
|
while(p) {
|
||||||
|
/* do we want to remove this key? */
|
||||||
|
if(p->s == AUTR_STATE_START || p->s == AUTR_STATE_REMOVED) {
|
||||||
|
struct autr_ta* np = p->next;
|
||||||
|
/* remove */
|
||||||
|
ldns_rr_free(p->rr);
|
||||||
|
free(p);
|
||||||
|
/* snip and go to next item */
|
||||||
|
*prevp = np;
|
||||||
|
p = np;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
prevp = &p->next;
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int autr_process_prime(struct module_env* env, struct val_env* ve,
|
int autr_process_prime(struct module_env* env, struct val_env* ve,
|
||||||
struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset)
|
struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset)
|
||||||
{
|
{
|
||||||
struct val_anchors* anchors = env->anchors;
|
int changed = 0;
|
||||||
log_assert(tp->autr);
|
log_assert(tp->autr);
|
||||||
/* autotrust update trust anchors */
|
/* autotrust update trust anchors */
|
||||||
/* the tp is locked, and stays locked unless it is deleted */
|
/* the tp is locked, and stays locked unless it is deleted */
|
||||||
|
|
||||||
|
/* TODO: check if marked as revoked, if so, unlock and return */
|
||||||
|
|
||||||
/* query_dnskeys(): */
|
/* query_dnskeys(): */
|
||||||
tp->autr->last_queried = *env->now;
|
tp->autr->last_queried = *env->now;
|
||||||
|
|
||||||
|
|
@ -907,25 +1273,46 @@ int autr_process_prime(struct module_env* env, struct val_env* ve,
|
||||||
return 1; /* trust point exists */
|
return 1; /* trust point exists */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tp->autr->last_success = *env->now;
|
||||||
tp->autr->query_failed = 0;
|
tp->autr->query_failed = 0;
|
||||||
|
|
||||||
/* update_events():
|
/* Add new trust anchors to the data structure
|
||||||
* - find minimum rrsig expiration interval
|
|
||||||
* - add new trust anchors to the data structure
|
|
||||||
* - note which trust anchors are seen this probe.
|
* - note which trust anchors are seen this probe.
|
||||||
* - note revoked (selfsigned) anchors.
|
* - note revoked (selfsigned) anchors.
|
||||||
* Set trustpoint query_interval and retry_time.
|
* Set trustpoint query_interval and retry_time.
|
||||||
|
* - find minimum rrsig expiration interval
|
||||||
*/
|
*/
|
||||||
if(!update_events(env, ve, tp, dnskey_rrset))
|
if(!update_events(env, ve, tp, dnskey_rrset, &changed)) {
|
||||||
|
log_err("malloc failure in autotrust update_events. "
|
||||||
|
"trust point unchanged.");
|
||||||
return 1; /* trust point unchanged, so exists */
|
return 1; /* trust point unchanged, so exists */
|
||||||
|
}
|
||||||
|
|
||||||
/* do_statetable():
|
/* - for every SEP key do the 5011 statetable.
|
||||||
* - for every SEP key do the 5011 statetable.
|
|
||||||
* - remove missing trustanchors (if too many).
|
* - remove missing trustanchors (if too many).
|
||||||
*/
|
*/
|
||||||
/* do_statetable(env, tp); */
|
if(!do_statetable(env, tp, &changed)) {
|
||||||
|
log_err("malloc failure in autotrust do_statetable. "
|
||||||
autr_assemble(tp);
|
"trust point unchanged.");
|
||||||
|
return 1; /* trust point unchanged, so exists */
|
||||||
return 1;
|
}
|
||||||
|
|
||||||
|
if(changed) {
|
||||||
|
verbose(VERB_ALGO, "autotrust: point changed, write to disk");
|
||||||
|
autr_cleanup_keys(tp);
|
||||||
|
autr_write_file(tp);
|
||||||
|
if(!autr_assemble(tp)) {
|
||||||
|
log_err("malloc failure assembling autotrust keys");
|
||||||
|
return 1; /* unchanged */
|
||||||
|
}
|
||||||
|
if(!tp->ds_rrset && !tp->dnskey_rrset) {
|
||||||
|
/* no more keys, all are revoked */
|
||||||
|
/* TODO: delete trust point:
|
||||||
|
* mark as revoked trust point.
|
||||||
|
* save name, unlock, take from tree, delete. */
|
||||||
|
return 0; /* trust point removed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; /* no changes */
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ struct autr_ta {
|
||||||
* Autotrust metadata for a trust point.
|
* Autotrust metadata for a trust point.
|
||||||
*/
|
*/
|
||||||
struct autr_point_data {
|
struct autr_point_data {
|
||||||
/** file to store the trust point in */
|
/** file to store the trust point in. chrootdir already applied. */
|
||||||
const char* file;
|
const char* file;
|
||||||
/** next probe time */
|
/** next probe time */
|
||||||
uint32_t next_probe_time;
|
uint32_t next_probe_time;
|
||||||
|
|
@ -91,6 +91,8 @@ struct autr_point_data {
|
||||||
|
|
||||||
/** last queried DNSKEY set */
|
/** last queried DNSKEY set */
|
||||||
time_t last_queried;
|
time_t last_queried;
|
||||||
|
/** last successful DNSKEY set */
|
||||||
|
time_t last_success;
|
||||||
/** how many times did it fail */
|
/** how many times did it fail */
|
||||||
uint8_t query_failed;
|
uint8_t query_failed;
|
||||||
/** when to query if !failed */
|
/** when to query if !failed */
|
||||||
|
|
@ -98,10 +100,6 @@ struct autr_point_data {
|
||||||
/** when to retry if failed */
|
/** when to retry if failed */
|
||||||
uint32_t retry_time;
|
uint32_t retry_time;
|
||||||
|
|
||||||
/** number of valid DNSKEYs */
|
|
||||||
uint8_t valid;
|
|
||||||
/** number of missing DNSKEYs */
|
|
||||||
uint8_t missing;
|
|
||||||
/** the keys */
|
/** the keys */
|
||||||
struct autr_ta* keys;
|
struct autr_ta* keys;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue