1224090Sdougb/* 2254402Serwin * Copyright (C) 2009, 2012 Internet Systems Consortium, Inc. ("ISC") 3224090Sdougb * 4224090Sdougb * Permission to use, copy, modify, and/or distribute this software for any 5224090Sdougb * purpose with or without fee is hereby granted, provided that the above 6224090Sdougb * copyright notice and this permission notice appear in all copies. 7224090Sdougb * 8224090Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9224090Sdougb * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10224090Sdougb * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11224090Sdougb * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12224090Sdougb * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13224090Sdougb * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14224090Sdougb * PERFORMANCE OF THIS SOFTWARE. 15224090Sdougb */ 16224090Sdougb 17234010Sdougb/* $Id: dnsconf.c,v 1.3 2009/09/02 23:48:02 tbox Exp $ */ 18224090Sdougb 19224090Sdougb/*! \file */ 20224090Sdougb 21224090Sdougb#include <config.h> 22224090Sdougb 23224090Sdougb#include <string.h> 24224090Sdougb 25224090Sdougb#include <isc/base64.h> 26224090Sdougb#include <isc/buffer.h> 27224090Sdougb#include <isc/file.h> 28224090Sdougb#include <isc/mem.h> 29224090Sdougb#include <isc/util.h> 30224090Sdougb 31224090Sdougb#include <isccfg/dnsconf.h> 32224090Sdougb 33224090Sdougb#include <dns/fixedname.h> 34224090Sdougb#include <dns/name.h> 35224090Sdougb#include <dns/rdata.h> 36224090Sdougb#include <dns/rdatastruct.h> 37224090Sdougb 38224090Sdougb#include <irs/dnsconf.h> 39224090Sdougb 40224090Sdougb#define IRS_DNSCONF_MAGIC ISC_MAGIC('D', 'c', 'f', 'g') 41224090Sdougb#define IRS_DNSCONF_VALID(c) ISC_MAGIC_VALID(c, IRS_DNSCONF_MAGIC) 42224090Sdougb 43224090Sdougb/*! 44224090Sdougb * configuration data structure 45224090Sdougb */ 46224090Sdougb 47224090Sdougbstruct irs_dnsconf { 48224090Sdougb unsigned int magic; 49224090Sdougb isc_mem_t *mctx; 50224090Sdougb irs_dnsconf_dnskeylist_t trusted_keylist; 51224090Sdougb}; 52224090Sdougb 53224090Sdougbstatic isc_result_t 54224090Sdougbconfigure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj, 55224090Sdougb dns_rdataclass_t rdclass) 56224090Sdougb{ 57224090Sdougb isc_mem_t *mctx = conf->mctx; 58224090Sdougb const cfg_obj_t *keys = NULL; 59224090Sdougb const cfg_obj_t *key, *keylist; 60224090Sdougb dns_fixedname_t fkeyname; 61224090Sdougb dns_name_t *keyname_base, *keyname; 62224090Sdougb const cfg_listelt_t *element, *element2; 63224090Sdougb isc_result_t result; 64224090Sdougb isc_uint32_t flags, proto, alg; 65224090Sdougb const char *keystr, *keynamestr; 66224090Sdougb unsigned char keydata[4096]; 67224090Sdougb isc_buffer_t keydatabuf_base, *keydatabuf; 68224090Sdougb dns_rdata_dnskey_t keystruct; 69224090Sdougb unsigned char rrdata[4096]; 70224090Sdougb isc_buffer_t rrdatabuf; 71224090Sdougb isc_region_t r; 72224090Sdougb isc_buffer_t namebuf; 73224090Sdougb irs_dnsconf_dnskey_t *keyent; 74224090Sdougb 75224090Sdougb cfg_map_get(cfgobj, "trusted-keys", &keys); 76224090Sdougb if (keys == NULL) 77224090Sdougb return (ISC_R_SUCCESS); 78224090Sdougb 79224090Sdougb for (element = cfg_list_first(keys); 80224090Sdougb element != NULL; 81224090Sdougb element = cfg_list_next(element)) { 82224090Sdougb keylist = cfg_listelt_value(element); 83224090Sdougb for (element2 = cfg_list_first(keylist); 84224090Sdougb element2 != NULL; 85224090Sdougb element2 = cfg_list_next(element2)) 86224090Sdougb { 87224090Sdougb keydatabuf = NULL; 88224090Sdougb keyname = NULL; 89224090Sdougb 90224090Sdougb key = cfg_listelt_value(element2); 91224090Sdougb 92224090Sdougb flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); 93224090Sdougb proto = cfg_obj_asuint32(cfg_tuple_get(key, 94224090Sdougb "protocol")); 95224090Sdougb alg = cfg_obj_asuint32(cfg_tuple_get(key, 96224090Sdougb "algorithm")); 97224090Sdougb keynamestr = cfg_obj_asstring(cfg_tuple_get(key, 98224090Sdougb "name")); 99224090Sdougb 100224090Sdougb keystruct.common.rdclass = rdclass; 101224090Sdougb keystruct.common.rdtype = dns_rdatatype_dnskey; 102224090Sdougb keystruct.mctx = NULL; 103224090Sdougb ISC_LINK_INIT(&keystruct.common, link); 104224090Sdougb 105224090Sdougb if (flags > 0xffff) 106224090Sdougb return (ISC_R_RANGE); 107224090Sdougb if (proto > 0xff) 108224090Sdougb return (ISC_R_RANGE); 109224090Sdougb if (alg > 0xff) 110224090Sdougb return (ISC_R_RANGE); 111224090Sdougb keystruct.flags = (isc_uint16_t)flags; 112224090Sdougb keystruct.protocol = (isc_uint8_t)proto; 113224090Sdougb keystruct.algorithm = (isc_uint8_t)alg; 114224090Sdougb 115224090Sdougb isc_buffer_init(&keydatabuf_base, keydata, 116224090Sdougb sizeof(keydata)); 117224090Sdougb isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); 118224090Sdougb 119224090Sdougb /* Configure key value */ 120224090Sdougb keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); 121224090Sdougb result = isc_base64_decodestring(keystr, 122224090Sdougb &keydatabuf_base); 123224090Sdougb if (result != ISC_R_SUCCESS) 124224090Sdougb return (result); 125224090Sdougb isc_buffer_usedregion(&keydatabuf_base, &r); 126224090Sdougb keystruct.datalen = r.length; 127224090Sdougb keystruct.data = r.base; 128224090Sdougb 129224090Sdougb result = dns_rdata_fromstruct(NULL, 130224090Sdougb keystruct.common.rdclass, 131224090Sdougb keystruct.common.rdtype, 132224090Sdougb &keystruct, &rrdatabuf); 133224090Sdougb if (result != ISC_R_SUCCESS) 134224090Sdougb return (result); 135224090Sdougb isc_buffer_usedregion(&rrdatabuf, &r); 136224090Sdougb result = isc_buffer_allocate(mctx, &keydatabuf, 137224090Sdougb r.length); 138224090Sdougb if (result != ISC_R_SUCCESS) 139224090Sdougb return (result); 140224090Sdougb result = isc_buffer_copyregion(keydatabuf, &r); 141224090Sdougb if (result != ISC_R_SUCCESS) 142224090Sdougb goto cleanup; 143224090Sdougb 144224090Sdougb /* Configure key name */ 145224090Sdougb dns_fixedname_init(&fkeyname); 146224090Sdougb keyname_base = dns_fixedname_name(&fkeyname); 147254402Serwin isc_buffer_constinit(&namebuf, keynamestr, 148254402Serwin strlen(keynamestr)); 149224090Sdougb isc_buffer_add(&namebuf, strlen(keynamestr)); 150224090Sdougb result = dns_name_fromtext(keyname_base, &namebuf, 151224090Sdougb dns_rootname, 0, NULL); 152224090Sdougb if (result != ISC_R_SUCCESS) 153224090Sdougb return (result); 154224090Sdougb keyname = isc_mem_get(mctx, sizeof(*keyname)); 155224090Sdougb if (keyname == NULL) { 156224090Sdougb result = ISC_R_NOMEMORY; 157224090Sdougb goto cleanup; 158224090Sdougb } 159224090Sdougb dns_name_init(keyname, NULL); 160224090Sdougb result = dns_name_dup(keyname_base, mctx, keyname); 161224090Sdougb if (result != ISC_R_SUCCESS) 162224090Sdougb goto cleanup; 163224090Sdougb 164224090Sdougb /* Add the key data to the list */ 165224090Sdougb keyent = isc_mem_get(mctx, sizeof(*keyent)); 166224090Sdougb if (keyent == NULL) { 167224090Sdougb dns_name_free(keyname, mctx); 168224090Sdougb result = ISC_R_NOMEMORY; 169224090Sdougb goto cleanup; 170224090Sdougb } 171224090Sdougb keyent->keyname = keyname; 172224090Sdougb keyent->keydatabuf = keydatabuf; 173224090Sdougb 174224090Sdougb ISC_LIST_APPEND(conf->trusted_keylist, keyent, link); 175224090Sdougb } 176224090Sdougb } 177224090Sdougb 178224090Sdougb return (ISC_R_SUCCESS); 179224090Sdougb 180224090Sdougb cleanup: 181224090Sdougb if (keydatabuf != NULL) 182224090Sdougb isc_buffer_free(&keydatabuf); 183224090Sdougb if (keyname != NULL) 184224090Sdougb isc_mem_put(mctx, keyname, sizeof(*keyname)); 185224090Sdougb 186224090Sdougb return (result); 187224090Sdougb} 188224090Sdougb 189224090Sdougbisc_result_t 190224090Sdougbirs_dnsconf_load(isc_mem_t *mctx, const char *filename, irs_dnsconf_t **confp) 191224090Sdougb{ 192224090Sdougb irs_dnsconf_t *conf; 193224090Sdougb cfg_parser_t *parser = NULL; 194224090Sdougb cfg_obj_t *cfgobj = NULL; 195224090Sdougb isc_result_t result = ISC_R_SUCCESS; 196224090Sdougb 197224090Sdougb REQUIRE(confp != NULL && *confp == NULL); 198224090Sdougb 199224090Sdougb conf = isc_mem_get(mctx, sizeof(*conf)); 200224090Sdougb if (conf == NULL) 201224090Sdougb return (ISC_R_NOMEMORY); 202224090Sdougb 203224090Sdougb conf->mctx = mctx; 204224090Sdougb ISC_LIST_INIT(conf->trusted_keylist); 205224090Sdougb 206224090Sdougb /* 207224090Sdougb * If the specified file does not exist, we'll simply with an empty 208224090Sdougb * configuration. 209224090Sdougb */ 210224090Sdougb if (!isc_file_exists(filename)) 211224090Sdougb goto cleanup; 212224090Sdougb 213224090Sdougb result = cfg_parser_create(mctx, NULL, &parser); 214224090Sdougb if (result != ISC_R_SUCCESS) 215224090Sdougb goto cleanup; 216224090Sdougb 217224090Sdougb result = cfg_parse_file(parser, filename, &cfg_type_dnsconf, 218224090Sdougb &cfgobj); 219224090Sdougb if (result != ISC_R_SUCCESS) 220224090Sdougb goto cleanup; 221224090Sdougb 222224090Sdougb result = configure_dnsseckeys(conf, cfgobj, dns_rdataclass_in); 223224090Sdougb 224224090Sdougb cleanup: 225224090Sdougb if (parser != NULL) { 226224090Sdougb if (cfgobj != NULL) 227224090Sdougb cfg_obj_destroy(parser, &cfgobj); 228224090Sdougb cfg_parser_destroy(&parser); 229224090Sdougb } 230224090Sdougb 231224090Sdougb conf->magic = IRS_DNSCONF_MAGIC; 232224090Sdougb 233224090Sdougb if (result == ISC_R_SUCCESS) 234224090Sdougb *confp = conf; 235224090Sdougb else 236224090Sdougb irs_dnsconf_destroy(&conf); 237224090Sdougb 238224090Sdougb return (result); 239224090Sdougb} 240224090Sdougb 241224090Sdougbvoid 242224090Sdougbirs_dnsconf_destroy(irs_dnsconf_t **confp) { 243224090Sdougb irs_dnsconf_t *conf; 244224090Sdougb irs_dnsconf_dnskey_t *keyent; 245224090Sdougb 246224090Sdougb REQUIRE(confp != NULL); 247224090Sdougb conf = *confp; 248224090Sdougb REQUIRE(IRS_DNSCONF_VALID(conf)); 249224090Sdougb 250224090Sdougb while ((keyent = ISC_LIST_HEAD(conf->trusted_keylist)) != NULL) { 251224090Sdougb ISC_LIST_UNLINK(conf->trusted_keylist, keyent, link); 252224090Sdougb 253224090Sdougb isc_buffer_free(&keyent->keydatabuf); 254224090Sdougb dns_name_free(keyent->keyname, conf->mctx); 255224090Sdougb isc_mem_put(conf->mctx, keyent->keyname, sizeof(dns_name_t)); 256224090Sdougb isc_mem_put(conf->mctx, keyent, sizeof(*keyent)); 257224090Sdougb } 258224090Sdougb 259224090Sdougb isc_mem_put(conf->mctx, conf, sizeof(*conf)); 260224090Sdougb 261224090Sdougb *confp = NULL; 262224090Sdougb} 263224090Sdougb 264224090Sdougbirs_dnsconf_dnskeylist_t * 265224090Sdougbirs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf) { 266224090Sdougb REQUIRE(IRS_DNSCONF_VALID(conf)); 267224090Sdougb 268224090Sdougb return (&conf->trusted_keylist); 269224090Sdougb} 270