configlexer.lo configlexer.o: util/configlexer.c config.h $(srcdir)/util/configyyrename.h \
$(srcdir)/util/config_file.h util/configparser.h
configparser.lo configparser.o: util/configparser.c config.h $(srcdir)/util/configyyrename.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/str2wire.h \
- $(srcdir)/sldns/rrdef.h
+ $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/tsig.h $(srcdir)/sldns/str2wire.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h
shm_main.lo shm_main.o: $(srcdir)/util/shm_side/shm_main.c config.h $(srcdir)/util/shm_side/shm_main.h \
$(srcdir)/libunbound/unbound.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
$(srcdir)/util/edns.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h \
$(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/respip/respip.h \
- $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h \
+ $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/util/tsig.h $(srcdir)/sldns/keyraw.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h \
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h \
- $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h \
+ $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h $(srcdir)/util/tsig.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.h \
$(srcdir)/libunbound/unbound-event.h config.h $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/libunbound/libworker.h \
$(srcdir)/util/config_file.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h \
- $(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h $(srcdir)/util/ub_event.h $(srcdir)/util/edns.h \
+ $(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h $(srcdir)/util/ub_event.h $(srcdir)/util/edns.h $(srcdir)/util/tsig.h \
$(srcdir)/util/storage/dnstree.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h \
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/services/cache/rrset.h \
#include "util/random.h"
#include "util/tube.h"
#include "util/net_help.h"
+#include "util/tsig.h"
#include "sldns/keyraw.h"
#include "respip/respip.h"
#include "iterator/iter_fwd.h"
free(daemon);
return NULL;
}
+ if(!(daemon->env->tsig_key_table = tsig_key_table_create())) {
+ auth_zones_delete(daemon->env->auth_zones);
+ acl_list_delete(daemon->acl_interface);
+ acl_list_delete(daemon->acl);
+ tcl_list_delete(daemon->tcl);
+ edns_known_options_delete(daemon->env);
+ edns_strings_delete(daemon->env->edns_strings);
+ free(daemon->env);
+ free(daemon);
+ return NULL;
+ }
return daemon;
}
daemon->use_response_ip = !respip_set_is_empty(
daemon->env->respip_set) || have_view_respip_cfg;
+ /* setup tsig keys */
+ if(!tsig_key_table_apply_cfg(daemon->env->tsig_key_table, daemon->cfg))
+ fatal_exit("Could not set up TSIG keys");
+
/* setup modules */
daemon_setup_modules(daemon);
edns_known_options_delete(daemon->env);
edns_strings_delete(daemon->env->edns_strings);
auth_zones_delete(daemon->env->auth_zones);
+ tsig_key_table_delete(daemon->env->tsig_key_table);
}
ub_randfree(daemon->rand);
alloc_clear(&daemon->superalloc);
#include "util/data/msgreply.h"
#include "util/storage/slabhash.h"
#include "util/edns.h"
+#include "util/tsig.h"
#include "sldns/sbuffer.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_hints.h"
return UB_INITFAIL;
listen_setup_locks();
log_edns_known_options(VERB_ALGO, ctx->env);
+ if(!tsig_key_table_apply_cfg(ctx->env->tsig_key_table, cfg))
+ return UB_INITFAIL;
ctx->local_zones = local_zones_create();
if(!ctx->local_zones)
return UB_NOMEM;
#include "util/tube.h"
#include "util/ub_event.h"
#include "util/edns.h"
+#include "util/tsig.h"
#include "services/modstack.h"
#include "services/localzone.h"
#include "services/cache/infra.h"
errno = ENOMEM;
return NULL;
}
+ ctx->env->tsig_key_table = tsig_key_table_create();
+ if(!ctx->env->tsig_key_table) {
+ auth_zones_delete(ctx->env->auth_zones);
+ edns_known_options_delete(ctx->env);
+ edns_strings_delete(ctx->env->edns_strings);
+ config_delete(ctx->env->cfg);
+ free(ctx->env);
+ ub_randfree(ctx->seed_rnd);
+ free(ctx);
+ errno = ENOMEM;
+ return NULL;
+ }
ctx->env->alloc = &ctx->superalloc;
ctx->env->worker = NULL;
config_delete(ctx->env->cfg);
edns_known_options_delete(ctx->env);
edns_strings_delete(ctx->env->edns_strings);
+ tsig_key_table_delete(ctx->env->tsig_key_table);
forwards_delete(ctx->env->fwds);
hints_delete(ctx->env->hints);
auth_zones_delete(ctx->env->auth_zones);
cfg->stubs = NULL;
cfg->forwards = NULL;
cfg->auths = NULL;
+ cfg->tsig_keys = NULL;
#ifdef CLIENT_SUBNET
cfg->client_subnet = NULL;
cfg->client_subnet_zone = NULL;
* max-client-subnet-ipv4, max-client-subnet-ipv6,
* min-client-subnet-ipv4, min-client-subnet-ipv6,
* max-ecs-tree-size-ipv4, max-ecs-tree-size-ipv6, ipsecmod_hook,
- * ipsecmod_whitelist. */
+ * ipsecmod_whitelist, tsig-key. */
return 0;
}
return 1;
* local-data-ptr - converted to local-data entries
* stub-zone, name, stub-addr, stub-host, stub-prime
* forward-zone, name, forward-addr, forward-host
+ * tsig-key
*/
else return 0;
return 1;
}
}
+void
+config_deltsig_key(struct config_tsig_key* p)
+{
+ if(!p) return;
+ free(p->name);
+ free(p->algorithm);
+ free(p->secret);
+ free(p);
+}
+
+void
+config_deltsig_keys(struct config_tsig_key* p)
+{
+ struct config_tsig_key* np;
+ while(p) {
+ np = p->next;
+ config_deltsig_key(p);
+ p = np;
+ }
+}
+
void
config_del_strarray(char** array, int num)
{
config_delstubs(cfg->forwards);
config_delauths(cfg->auths);
config_delviews(cfg->views);
+ config_deltsig_keys(cfg->tsig_keys);
config_delstrlist(cfg->donotqueryaddrs);
config_delstrlist(cfg->root_hints);
#ifdef CLIENT_SUBNET
struct config_stub;
struct config_auth;
struct config_view;
+struct config_tsig_key;
struct config_strlist;
struct config_str2list;
struct config_str3list;
struct config_auth* auths;
/** the views definitions, linked list */
struct config_view* views;
+ /** the tsig-key definitions, linked list */
+ struct config_tsig_key* tsig_keys;
/** list of donotquery addresses, linked list */
struct config_strlist* donotqueryaddrs;
#ifdef CLIENT_SUBNET
struct config_str2list* respip_data;
};
+/**
+ * Tsig-key config options
+ */
+struct config_tsig_key {
+ /** next in list */
+ struct config_tsig_key* next;
+ /** name of the tsig key */
+ char* name;
+ /** algorithm */
+ char* algorithm;
+ /** secret date, in base64 */
+ char* secret;
+};
+
/**
* List of strings for config options
*/
*/
void config_delviews(struct config_view* list);
+/**
+ * Delete a tsig_key item
+ * @param p: tsig_key item
+ */
+void config_deltsig_key(struct config_tsig_key* p);
+
+/**
+ * Delete items in config tsig_key list.
+ * @param list: list.
+ */
+void config_deltsig_keys(struct config_tsig_key* list);
+
/** check if config for remote control turns on IP-address interface
* with certificates or a named pipe without certificates. */
int options_remote_is_address(struct config_file* cfg);
iter-scrub-ns{COLON} { YDVAR(1, VAR_ITER_SCRUB_NS) }
iter-scrub-cname{COLON} { YDVAR(1, VAR_ITER_SCRUB_CNAME) }
max-global-quota{COLON} { YDVAR(1, VAR_MAX_GLOBAL_QUOTA) }
+tsig-key{COLON} { YDVAR(0, VAR_TSIG_KEY) }
+algorithm{COLON} { YDVAR(1, VAR_ALGORITHM) }
+secret{COLON} { YDVAR(1, VAR_SECRET) }
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
/* Quoted strings. Strip leading and ending quotes */
#include "util/configyyrename.h"
#include "util/config_file.h"
#include "util/net_help.h"
+#include "util/tsig.h"
#include "sldns/str2wire.h"
+#include "sldns/parseutil.h"
int ub_c_lex(void);
void ub_c_error(const char *message);
%token VAR_LOG_DESTADDR VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED
%token VAR_COOKIE_SECRET_FILE VAR_ITER_SCRUB_NS VAR_ITER_SCRUB_CNAME
%token VAR_MAX_GLOBAL_QUOTA VAR_HARDEN_UNVERIFIED_GLUE VAR_LOG_TIME_ISO
+%token VAR_TSIG_KEY VAR_ALGORITHM VAR_SECRET
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
rcstart contents_rc | dtstart contents_dt | view_clause |
dnscstart contents_dnsc | cachedbstart contents_cachedb |
ipsetstart contents_ipset | authstart contents_auth |
- rpzstart contents_rpz | dynlibstart contents_dl |
+ rpzstart contents_rpz | dynlibstart contents_dl | tsig_key_clause |
force_toplevel
;
force_toplevel: VAR_FORCE_TOPLEVEL
yyerror("out of memory");
}
;
+tsig_key_clause: tsig_key_start contents_tsig_key
+ {
+ /* tsig-key end */
+ if(cfg_parser->cfg->tsig_keys) {
+ if(!cfg_parser->cfg->tsig_keys->name)
+ yyerror("tsig-key without name");
+ else if(!cfg_parser->cfg->tsig_keys->algorithm)
+ ub_c_error_msg("tsig-key %s has no algorithm",
+ cfg_parser->cfg->tsig_keys->name);
+ else if(!cfg_parser->cfg->tsig_keys->secret)
+ ub_c_error_msg("tsig-key %s has no secret blob",
+ cfg_parser->cfg->tsig_keys->name);
+ }
+ }
+ ;
+tsig_key_start: VAR_TSIG_KEY
+ {
+ struct config_tsig_key* s;
+ OUTYY(("\nP(tsig-key:)\n"));
+ cfg_parser->started_toplevel = 1;
+ s = (struct config_tsig_key*)calloc(1,
+ sizeof(struct config_tsig_key));
+ if(s) {
+ s->next = cfg_parser->cfg->tsig_keys;
+ cfg_parser->cfg->tsig_keys = s;
+ } else {
+ yyerror("out of memory");
+ }
+ }
+ ;
+contents_tsig_key: contents_tsig_key content_tsig_key
+ | ;
+content_tsig_key: tsig_key_name | tsig_key_algorithm | tsig_key_secret
+ ;
+tsig_key_name: VAR_NAME STRING_ARG
+ {
+ uint8_t buf[LDNS_MAX_DOMAINLEN+1];
+ size_t len = sizeof(buf);
+ int r;
+
+ OUTYY(("P(name:%s)\n", $2));
+ free(cfg_parser->cfg->tsig_keys->name);
+ cfg_parser->cfg->tsig_keys->name = $2;
+
+ if((r=sldns_str2wire_dname_buf($2, buf, &len))!=0)
+ ub_c_error_msg("could not parse tsig key name"
+ " '%s':%d: %s", $2, LDNS_WIREPARSE_OFFSET(r),
+ sldns_get_errorstr_parse(r));
+ }
+tsig_key_algorithm: VAR_ALGORITHM STRING_ARG
+ {
+ OUTYY(("P(algorithm:%s)\n", $2));
+ free(cfg_parser->cfg->tsig_keys->algorithm);
+ cfg_parser->cfg->tsig_keys->algorithm = $2;
+ if(!tsig_algo_check_name($2))
+ ub_c_error_msg("could not parse tsig key algorithm '%s'",
+ $2);
+ }
+tsig_key_secret: VAR_SECRET STRING_ARG
+ {
+ uint8_t data[16384];
+ int size;
+
+ OUTYY(("P(secret:%s)\n", $2));
+ free(cfg_parser->cfg->tsig_keys->secret);
+ cfg_parser->cfg->tsig_keys->secret = $2;
+
+ size = sldns_b64_pton($2, data, sizeof(data));
+ if(size == -1) {
+ ub_c_error_msg("cannot base64 decode tsig secret %s",
+ cfg_parser->cfg->tsig_keys->name?
+ cfg_parser->cfg->tsig_keys->name:"");
+ } else if(size != 0) {
+ explicit_bzero(data, size);
+ }
+ }
server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG
{
OUTYY(("P(disable_dnssec_lame_check:%s)\n", $2));
struct respip_set;
struct respip_client_info;
struct respip_addr_info;
+struct tsig_key_table;
struct module_stack;
/** Maximum number of modules in operation */
struct views* views;
/** response-ip set with associated actions and tags. */
struct respip_set* respip_set;
+ /** the TSIG keys */
+ struct tsig_key_table* tsig_key_table;
/** module specific data. indexed by module id. */
void* modinfo[MAX_MODULE];
#include "config.h"
#include "util/tsig.h"
+#include "util/config_file.h"
#include "util/log.h"
+#include "sldns/parseutil.h"
#include "sldns/pkthdr.h"
#include "sldns/rrdef.h"
#include "sldns/sbuffer.h"
+#include "sldns/str2wire.h"
#include "util/data/msgparse.h"
#include "util/data/dname.h"
#include <openssl/evp.h>
free(key_table);
}
+/** Create a tsig_key */
+static struct tsig_key*
+tsig_key_create(const char* name, const char* algorithm, const char* secret)
+{
+ struct tsig_key* key = (struct tsig_key*)calloc(1, sizeof(*key));
+ int ret;
+ if(!key) {
+ log_err("out of memory");
+ return NULL;
+ }
+ key->node.key = key;
+ key->name_str = strdup(name);
+ if(!key->name_str) {
+ log_err("out of memory");
+ tsig_key_delete(key);
+ return NULL;
+ }
+ key->algo = tsig_algo_find_name(algorithm);
+ if(!key->algo) {
+ log_err("tsig key %s could not parse algorithm '%s'",
+ name, algorithm);
+ tsig_key_delete(key);
+ return NULL;
+ }
+ key->name = sldns_str2wire_dname(name, &key->name_len);
+ if(!key->name) {
+ log_err("tsig key %s could not parse name into wireformat",
+ name);
+ tsig_key_delete(key);
+ return NULL;
+ }
+
+ key->data_len = sldns_b64_pton_calculate_size(strlen(secret));
+ if(key->data_len == 0)
+ key->data = NULL;
+ else key->data = malloc(key->data_len);
+ if(!key->data) {
+ log_err("out of memory");
+ tsig_key_delete(key);
+ return NULL;
+ }
+ ret = sldns_b64_pton(secret, key->data, key->data_len);
+ if(ret == -1 || ret > (int)key->data_len) {
+ log_err("tsig key %s could not base64 decode secret blob",
+ name);
+ tsig_key_delete(key);
+ return NULL;
+ }
+ key->data_len = ret;
+
+ return key;
+}
+
+/** Add a key to the TSIG key table. */
+static int
+tsig_key_table_add_key(struct tsig_key_table* key_table,
+ struct config_tsig_key* s)
+{
+ struct tsig_key* key;
+ key = tsig_key_create(s->name, s->algorithm, s->secret);
+ if(!key)
+ return 0;
+ /* Wipe the secret from config, it is in the key_table. */
+ if(s->secret[0] != 0)
+ explicit_bzero(s->secret, strlen(s->secret));
+
+ lock_rw_wrlock(&key_table->lock);
+ if(!rbtree_insert(key_table->tree, &key->node)) {
+ log_warn("duplicate tsig-key: %s", key->name_str);
+ lock_rw_unlock(&key_table->lock);
+ tsig_key_delete(key);
+ return 0;
+ }
+ lock_rw_unlock(&key_table->lock);
+ return 1;
+}
+
+int
+tsig_key_table_apply_cfg(struct tsig_key_table* key_table,
+ struct config_file* cfg)
+{
+ struct config_tsig_key* s;
+ for(s = cfg->tsig_keys; s; s = s->next) {
+ if(!tsig_key_table_add_key(key_table, s))
+ return 0;
+ }
+ return 1;
+}
+
void tsig_key_delete(struct tsig_key* key)
{
if(!key)
free(key->name);
if(key->data) {
/* The secret data is removed. */
- explicit_bzero(key->data, key->data_len);
+ if(key->data_len > 0)
+ explicit_bzero(key->data, key->data_len);
free(key->data);
}
free(key);
#include "util/locks.h"
#include "util/rbtree.h"
struct sldns_buffer;
+struct config_file;
/**
* TSIG record, the RR that is in the packet.
*/
void tsig_key_table_delete(struct tsig_key_table* key_table);
+/**
+ * Apply config to the tsig key table.
+ * @param key_table: the tsig key table.
+ * @param cfg: the config to read.
+ * @return false on failure.
+ */
+int tsig_key_table_apply_cfg(struct tsig_key_table* key_table,
+ struct config_file* cfg);
+
/**
* Delete TSIG key.
* @param key: to delete