1135446Strhodes/* 2254402Serwin * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 1999-2001 Internet Software Consortium. 4135446Strhodes * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18234010Sdougb/* $Id: tsigconf.c,v 1.35 2011/01/11 23:47:12 tbox Exp $ */ 19135446Strhodes 20170222Sdougb/*! \file */ 21170222Sdougb 22135446Strhodes#include <config.h> 23135446Strhodes 24135446Strhodes#include <isc/base64.h> 25135446Strhodes#include <isc/buffer.h> 26135446Strhodes#include <isc/mem.h> 27135446Strhodes#include <isc/string.h> 28135446Strhodes 29135446Strhodes#include <isccfg/cfg.h> 30135446Strhodes 31135446Strhodes#include <dns/tsig.h> 32135446Strhodes#include <dns/result.h> 33135446Strhodes 34135446Strhodes#include <named/log.h> 35135446Strhodes 36135446Strhodes#include <named/config.h> 37135446Strhodes#include <named/tsigconf.h> 38135446Strhodes 39135446Strhodesstatic isc_result_t 40165071Sdougbadd_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring, 41165071Sdougb isc_mem_t *mctx) 42165071Sdougb{ 43170222Sdougb dns_tsigkey_t *tsigkey = NULL; 44165071Sdougb const cfg_listelt_t *element; 45165071Sdougb const cfg_obj_t *key = NULL; 46165071Sdougb const char *keyid = NULL; 47135446Strhodes unsigned char *secret = NULL; 48135446Strhodes int secretalloc = 0; 49135446Strhodes int secretlen = 0; 50135446Strhodes isc_result_t ret; 51135446Strhodes isc_stdtime_t now; 52170222Sdougb isc_uint16_t bits; 53135446Strhodes 54135446Strhodes for (element = cfg_list_first(list); 55135446Strhodes element != NULL; 56135446Strhodes element = cfg_list_next(element)) 57135446Strhodes { 58165071Sdougb const cfg_obj_t *algobj = NULL; 59165071Sdougb const cfg_obj_t *secretobj = NULL; 60135446Strhodes dns_name_t keyname; 61135446Strhodes dns_name_t *alg; 62165071Sdougb const char *algstr; 63135446Strhodes char keynamedata[1024]; 64135446Strhodes isc_buffer_t keynamesrc, keynamebuf; 65165071Sdougb const char *secretstr; 66135446Strhodes isc_buffer_t secretbuf; 67135446Strhodes 68135446Strhodes key = cfg_listelt_value(element); 69135446Strhodes keyid = cfg_obj_asstring(cfg_map_getname(key)); 70135446Strhodes 71135446Strhodes algobj = NULL; 72135446Strhodes secretobj = NULL; 73135446Strhodes (void)cfg_map_get(key, "algorithm", &algobj); 74135446Strhodes (void)cfg_map_get(key, "secret", &secretobj); 75135446Strhodes INSIST(algobj != NULL && secretobj != NULL); 76135446Strhodes 77135446Strhodes /* 78135446Strhodes * Create the key name. 79135446Strhodes */ 80135446Strhodes dns_name_init(&keyname, NULL); 81254402Serwin isc_buffer_constinit(&keynamesrc, keyid, strlen(keyid)); 82135446Strhodes isc_buffer_add(&keynamesrc, strlen(keyid)); 83135446Strhodes isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata)); 84135446Strhodes ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname, 85224092Sdougb DNS_NAME_DOWNCASE, &keynamebuf); 86135446Strhodes if (ret != ISC_R_SUCCESS) 87135446Strhodes goto failure; 88135446Strhodes 89135446Strhodes /* 90135446Strhodes * Create the algorithm. 91135446Strhodes */ 92135446Strhodes algstr = cfg_obj_asstring(algobj); 93170222Sdougb if (ns_config_getkeyalgorithm(algstr, &alg, &bits) 94170222Sdougb != ISC_R_SUCCESS) { 95135446Strhodes cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR, 96170222Sdougb "key '%s': has a unsupported algorithm '%s'", 97170222Sdougb keyid, algstr); 98135446Strhodes ret = DNS_R_BADALG; 99135446Strhodes goto failure; 100135446Strhodes } 101135446Strhodes 102135446Strhodes secretstr = cfg_obj_asstring(secretobj); 103135446Strhodes secretalloc = secretlen = strlen(secretstr) * 3 / 4; 104135446Strhodes secret = isc_mem_get(mctx, secretlen); 105135446Strhodes if (secret == NULL) { 106135446Strhodes ret = ISC_R_NOMEMORY; 107135446Strhodes goto failure; 108135446Strhodes } 109135446Strhodes isc_buffer_init(&secretbuf, secret, secretlen); 110135446Strhodes ret = isc_base64_decodestring(secretstr, &secretbuf); 111135446Strhodes if (ret != ISC_R_SUCCESS) 112135446Strhodes goto failure; 113135446Strhodes secretlen = isc_buffer_usedlength(&secretbuf); 114135446Strhodes 115135446Strhodes isc_stdtime_get(&now); 116135446Strhodes ret = dns_tsigkey_create(&keyname, alg, secret, secretlen, 117135446Strhodes ISC_FALSE, NULL, now, now, 118170222Sdougb mctx, ring, &tsigkey); 119135446Strhodes isc_mem_put(mctx, secret, secretalloc); 120135446Strhodes secret = NULL; 121135446Strhodes if (ret != ISC_R_SUCCESS) 122135446Strhodes goto failure; 123170222Sdougb /* 124170222Sdougb * Set digest bits. 125170222Sdougb */ 126170222Sdougb dst_key_setbits(tsigkey->key, bits); 127170222Sdougb dns_tsigkey_detach(&tsigkey); 128135446Strhodes } 129135446Strhodes 130135446Strhodes return (ISC_R_SUCCESS); 131135446Strhodes 132135446Strhodes failure: 133135446Strhodes cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, 134135446Strhodes "configuring key '%s': %s", keyid, 135135446Strhodes isc_result_totext(ret)); 136135446Strhodes 137135446Strhodes if (secret != NULL) 138135446Strhodes isc_mem_put(mctx, secret, secretalloc); 139135446Strhodes return (ret); 140135446Strhodes} 141135446Strhodes 142135446Strhodesisc_result_t 143165071Sdougbns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, 144135446Strhodes isc_mem_t *mctx, dns_tsig_keyring_t **ringp) 145135446Strhodes{ 146165071Sdougb const cfg_obj_t *maps[3]; 147165071Sdougb const cfg_obj_t *keylist; 148135446Strhodes dns_tsig_keyring_t *ring = NULL; 149135446Strhodes isc_result_t result; 150135446Strhodes int i; 151135446Strhodes 152224092Sdougb REQUIRE(ringp != NULL && *ringp == NULL); 153224092Sdougb 154135446Strhodes i = 0; 155135446Strhodes if (config != NULL) 156135446Strhodes maps[i++] = config; 157135446Strhodes if (vconfig != NULL) 158135446Strhodes maps[i++] = cfg_tuple_get(vconfig, "options"); 159135446Strhodes maps[i] = NULL; 160135446Strhodes 161135446Strhodes result = dns_tsigkeyring_create(mctx, &ring); 162135446Strhodes if (result != ISC_R_SUCCESS) 163135446Strhodes return (result); 164135446Strhodes 165135446Strhodes for (i = 0; ; i++) { 166135446Strhodes if (maps[i] == NULL) 167135446Strhodes break; 168135446Strhodes keylist = NULL; 169135446Strhodes result = cfg_map_get(maps[i], "key", &keylist); 170135446Strhodes if (result != ISC_R_SUCCESS) 171135446Strhodes continue; 172135446Strhodes result = add_initial_keys(keylist, ring, mctx); 173135446Strhodes if (result != ISC_R_SUCCESS) 174135446Strhodes goto failure; 175135446Strhodes } 176135446Strhodes 177135446Strhodes *ringp = ring; 178135446Strhodes return (ISC_R_SUCCESS); 179135446Strhodes 180135446Strhodes failure: 181224092Sdougb dns_tsigkeyring_detach(&ring); 182135446Strhodes return (result); 183135446Strhodes} 184