From b8a2dfb2c93efa7ce06082267aedd82e9577a35c Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Tue, 25 Aug 2009 10:02:17 +0000 Subject: [PATCH] revoke point handling git-svn-id: file:///svn/unbound/trunk@1777 be551aaa-1e26-0410-a405-d3ace91eadb9 --- daemon/daemon.c | 2 +- doc/Changelog | 1 + validator/autotrust.c | 69 +++++++++++++++++++++++++++++++++++++----- validator/autotrust.h | 3 ++ validator/val_anchor.c | 14 ++++++--- validator/val_anchor.h | 10 ++++++ 6 files changed, 86 insertions(+), 13 deletions(-) diff --git a/daemon/daemon.c b/daemon/daemon.c index 4ebebe07e..16be3534e 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -176,7 +176,7 @@ daemon_init() #endif OpenSSL_add_all_algorithms(); /* grab the COMP method ptr because openssl leaks it */ - comp_meth = SSL_COMP_get_compression_methods(); + comp_meth = (void*)SSL_COMP_get_compression_methods(); (void)SSL_library_init(); #ifdef HAVE_TZSET /* init timezone info while we are not chrooted yet */ diff --git a/doc/Changelog b/doc/Changelog index 4817fb4f7..612f53c31 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -2,6 +2,7 @@ - fixup memleak in trust anchor unsupported algorithm check. - iana portlist updated. - autotrust options: add-holddown, del-holddown, keep-missing. + - autotrust store revoked status of trust points. 24 August 2009: Wouter - cleaner memory allocation on exit. autotrust test routines. diff --git a/validator/autotrust.c b/validator/autotrust.c index 7efbe49be..61cea54c4 100644 --- a/validator/autotrust.c +++ b/validator/autotrust.c @@ -50,6 +50,7 @@ #include "util/module.h" #include "util/net_help.h" #include "util/config_file.h" +#include "util/regional.h" /** number of times a key must be seen before it can become valid */ #define MIN_PENDINGCOUNT 2 @@ -599,6 +600,7 @@ parse_id(struct val_anchors* anchors, char* line) * @param anchor: the anchor as result value or previously returned anchor * value to read the variable lines into. * @return: 0 no match, -1 failed syntax error, +1 success line read. + * +2 revoked trust anchor file. */ static int parse_var_line(char* line, struct val_anchors* anchors, @@ -610,6 +612,12 @@ parse_var_line(char* line, struct val_anchors* anchors, *anchor = parse_id(anchors, line+6); if(!*anchor) return -1; else return 1; + } else if(strncmp(line, ";;REVOKED", 9) == 0) { + if(tp) { + log_err("REVOKED statement must be at start of file"); + return -1; + } + return 2; } else if(strncmp(line, ";;last_queried: ", 16) == 0) { if(!tp) return -1; lock_basic_lock(&tp->lock); @@ -663,7 +671,6 @@ int autr_read_file(struct val_anchors* anchors, const char* nm) return 0; } verbose(VERB_ALGO, "reading autotrust anchor file %s", nm); - /* TODO: read line to see if special marker for revoked tp */ while (fgets(line, (int)sizeof(line), fd) != NULL) { line_nr++; if((r = parse_var_line(line, anchors, &tp)) == -1) { @@ -672,6 +679,10 @@ int autr_read_file(struct val_anchors* anchors, const char* nm) return 0; } else if(r == 1) { continue; + } else if(r == 2) { + log_warn("trust anchor %s has been revoked", nm); + fclose(fd); + return 1; } if (!str_contains_data(line, ';')) continue; /* empty lines allowed */ @@ -757,6 +768,14 @@ void autr_write_file(struct module_env* env, struct trust_anchor* tp) } /* write pretty header */ fprintf(out, "; autotrust trust anchor file\n"); + if(tp->autr->revoked) { + fprintf(out, ";;REVOKED\n"); + fprintf(out, "; The zone has all keys revoked, and is\n" + "; considered as if it has no trust anchors.\n" + "; the remainder of the file is the last probe.\n" + "; to restart the trust anchor, overwrite this file.\n" + "; with one containing valid DNSKEYs or DSes.\n"); + } print_id(out, env, tp->name, tp->namelen, tp->dclass); fprintf(out, ";;last_queried: %u ;;%s", (unsigned int)tp->autr->last_queried, @@ -771,9 +790,6 @@ void autr_write_file(struct module_env* env, struct trust_anchor* tp) fprintf(out, ";;query_interval: %d\n", (int)tp->autr->query_interval); fprintf(out, ";;retry_time: %d\n", (int)tp->autr->retry_time); - /* write revoked tp special marker */ - /* TODO */ - /* write anchors */ for(ta=tp->autr->keys; ta; ta=ta->next) { char* str; @@ -1399,6 +1415,36 @@ autr_cleanup_keys(struct trust_anchor* tp) } } +/** Delete trust point that was revoked */ +static void +autr_tp_remove(struct module_env* env, struct trust_anchor* tp) +{ + struct trust_anchor key; + /* save name */ + memset(&key, 0, sizeof(key)); + key.node.key = &key; + key.name = regional_alloc_init(env->scratch, tp->name, tp->namelen); + if(!key.name) { + log_err("out of scratch memory in trust point delete"); + /* the revoked=1 flag on it saves the day, but wastes memory */ + return; + } + key.namelen = tp->namelen; + key.namelabs = tp->namelabs; + key.dclass = tp->dclass; + + /* unlock */ + lock_basic_unlock(&tp->lock); + + /* take from tree. It could be deleted by someone else. */ + lock_basic_lock(&env->anchors->lock); + (void)rbtree_delete(env->anchors->tree, &key); + anchors_init_parents_locked(env->anchors); + lock_basic_unlock(&env->anchors->lock); + /* delete */ + autr_point_delete(tp); +} + int autr_process_prime(struct module_env* env, struct val_env* ve, struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset) { @@ -1407,7 +1453,15 @@ int autr_process_prime(struct module_env* env, struct val_env* ve, /* autotrust update trust anchors */ /* the tp is locked, and stays locked unless it is deleted */ - /* TODO: check if marked as revoked, if so, unlock and return */ + /* we could just catch the anchor here while another thread + * is busy deleting it. Just unlock and let the other do its job */ + if(tp->autr->revoked) { + log_nametypeclass(VERB_ALGO, "autotrust not processed, " + "trust point revoked", tp->name, + LDNS_RR_TYPE_DNSKEY, tp->dclass); + lock_basic_unlock(&tp->lock); + return 0; /* it is revoked */ + } /* query_dnskeys(): */ tp->autr->last_queried = *env->now; @@ -1460,9 +1514,8 @@ int autr_process_prime(struct module_env* env, struct val_env* ve, } 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. */ + tp->autr->revoked = 1; + autr_tp_remove(env, tp); return 0; /* trust point removed */ } } else verbose(VERB_ALGO, "autotrust: no changes"); diff --git a/validator/autotrust.h b/validator/autotrust.h index 4b12a3644..ff336ce63 100644 --- a/validator/autotrust.h +++ b/validator/autotrust.h @@ -80,6 +80,7 @@ struct autr_ta { /** * Autotrust metadata for a trust point. + * This is part of the struct trust_anchor data. */ struct autr_point_data { /** file to store the trust point in. chrootdir already applied. */ @@ -104,6 +105,8 @@ struct autr_point_data { /** how many times did it fail */ uint8_t query_failed; + /** true if the trust point has been revoked */ + uint8_t revoked; }; /** diff --git a/validator/val_anchor.c b/validator/val_anchor.c index e7517f8fe..fa49fbb97 100644 --- a/validator/val_anchor.c +++ b/validator/val_anchor.c @@ -120,15 +120,13 @@ anchors_delete(struct val_anchors* anchors) free(anchors); } -/** initialise parent pointers in the tree */ -static void -init_parents(struct val_anchors* anchors) +void +anchors_init_parents_locked(struct val_anchors* anchors) { struct trust_anchor* node, *prev = NULL, *p; int m; /* nobody else can grab locks because we hold the main lock. * Thus the previous items, after unlocked, are not deleted */ - lock_basic_lock(&anchors->lock); RBTREE_FOR(node, struct trust_anchor*, anchors->tree) { lock_basic_lock(&node->lock); node->parent = NULL; @@ -153,6 +151,14 @@ init_parents(struct val_anchors* anchors) lock_basic_unlock(&node->lock); prev = node; } +} + +/** initialise parent pointers in the tree */ +static void +init_parents(struct val_anchors* anchors) +{ + lock_basic_lock(&anchors->lock); + anchors_init_parents_locked(anchors); lock_basic_unlock(&anchors->lock); } diff --git a/validator/val_anchor.h b/validator/val_anchor.h index af530ba2e..bc39efb07 100644 --- a/validator/val_anchor.h +++ b/validator/val_anchor.h @@ -141,6 +141,16 @@ void anchors_delete(struct val_anchors* anchors); */ int anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg); +/** + * Recalculate parent pointers. The caller must hold the lock on the + * anchors structure (say after removing an item from the rbtree). + * Caller must not hold any locks on trust anchors. + * After the call is complete the parent pointers are updated and an item + * just removed is no longer referenced in parent pointers. + * @param anchors: the structure to update. + */ +void anchors_init_parents_locked(struct val_anchors* anchors); + /** * Given a qname/qclass combination, find the trust anchor closest above it. * Or return NULL if none exists.