1/* 2 * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: tsigconf.c,v 1.35 2011/01/11 23:47:12 tbox Exp $ */ 19 20/*! \file */ 21 22#include <config.h> 23 24#include <isc/base64.h> 25#include <isc/buffer.h> 26#include <isc/mem.h> 27#include <isc/string.h> 28 29#include <isccfg/cfg.h> 30 31#include <dns/tsig.h> 32#include <dns/result.h> 33 34#include <named/log.h> 35 36#include <named/config.h> 37#include <named/tsigconf.h> 38 39static isc_result_t 40add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring, 41 isc_mem_t *mctx) 42{ 43 dns_tsigkey_t *tsigkey = NULL; 44 const cfg_listelt_t *element; 45 const cfg_obj_t *key = NULL; 46 const char *keyid = NULL; 47 unsigned char *secret = NULL; 48 int secretalloc = 0; 49 int secretlen = 0; 50 isc_result_t ret; 51 isc_stdtime_t now; 52 isc_uint16_t bits; 53 54 for (element = cfg_list_first(list); 55 element != NULL; 56 element = cfg_list_next(element)) 57 { 58 const cfg_obj_t *algobj = NULL; 59 const cfg_obj_t *secretobj = NULL; 60 dns_name_t keyname; 61 dns_name_t *alg; 62 const char *algstr; 63 char keynamedata[1024]; 64 isc_buffer_t keynamesrc, keynamebuf; 65 const char *secretstr; 66 isc_buffer_t secretbuf; 67 68 key = cfg_listelt_value(element); 69 keyid = cfg_obj_asstring(cfg_map_getname(key)); 70 71 algobj = NULL; 72 secretobj = NULL; 73 (void)cfg_map_get(key, "algorithm", &algobj); 74 (void)cfg_map_get(key, "secret", &secretobj); 75 INSIST(algobj != NULL && secretobj != NULL); 76 77 /* 78 * Create the key name. 79 */ 80 dns_name_init(&keyname, NULL); 81 isc_buffer_constinit(&keynamesrc, keyid, strlen(keyid)); 82 isc_buffer_add(&keynamesrc, strlen(keyid)); 83 isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata)); 84 ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname, 85 DNS_NAME_DOWNCASE, &keynamebuf); 86 if (ret != ISC_R_SUCCESS) 87 goto failure; 88 89 /* 90 * Create the algorithm. 91 */ 92 algstr = cfg_obj_asstring(algobj); 93 if (ns_config_getkeyalgorithm(algstr, &alg, &bits) 94 != ISC_R_SUCCESS) { 95 cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR, 96 "key '%s': has a unsupported algorithm '%s'", 97 keyid, algstr); 98 ret = DNS_R_BADALG; 99 goto failure; 100 } 101 102 secretstr = cfg_obj_asstring(secretobj); 103 secretalloc = secretlen = strlen(secretstr) * 3 / 4; 104 secret = isc_mem_get(mctx, secretlen); 105 if (secret == NULL) { 106 ret = ISC_R_NOMEMORY; 107 goto failure; 108 } 109 isc_buffer_init(&secretbuf, secret, secretlen); 110 ret = isc_base64_decodestring(secretstr, &secretbuf); 111 if (ret != ISC_R_SUCCESS) 112 goto failure; 113 secretlen = isc_buffer_usedlength(&secretbuf); 114 115 isc_stdtime_get(&now); 116 ret = dns_tsigkey_create(&keyname, alg, secret, secretlen, 117 ISC_FALSE, NULL, now, now, 118 mctx, ring, &tsigkey); 119 isc_mem_put(mctx, secret, secretalloc); 120 secret = NULL; 121 if (ret != ISC_R_SUCCESS) 122 goto failure; 123 /* 124 * Set digest bits. 125 */ 126 dst_key_setbits(tsigkey->key, bits); 127 dns_tsigkey_detach(&tsigkey); 128 } 129 130 return (ISC_R_SUCCESS); 131 132 failure: 133 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, 134 "configuring key '%s': %s", keyid, 135 isc_result_totext(ret)); 136 137 if (secret != NULL) 138 isc_mem_put(mctx, secret, secretalloc); 139 return (ret); 140} 141 142isc_result_t 143ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, 144 isc_mem_t *mctx, dns_tsig_keyring_t **ringp) 145{ 146 const cfg_obj_t *maps[3]; 147 const cfg_obj_t *keylist; 148 dns_tsig_keyring_t *ring = NULL; 149 isc_result_t result; 150 int i; 151 152 REQUIRE(ringp != NULL && *ringp == NULL); 153 154 i = 0; 155 if (config != NULL) 156 maps[i++] = config; 157 if (vconfig != NULL) 158 maps[i++] = cfg_tuple_get(vconfig, "options"); 159 maps[i] = NULL; 160 161 result = dns_tsigkeyring_create(mctx, &ring); 162 if (result != ISC_R_SUCCESS) 163 return (result); 164 165 for (i = 0; ; i++) { 166 if (maps[i] == NULL) 167 break; 168 keylist = NULL; 169 result = cfg_map_get(maps[i], "key", &keylist); 170 if (result != ISC_R_SUCCESS) 171 continue; 172 result = add_initial_keys(keylist, ring, mctx); 173 if (result != ISC_R_SUCCESS) 174 goto failure; 175 } 176 177 *ringp = ring; 178 return (ISC_R_SUCCESS); 179 180 failure: 181 dns_tsigkeyring_detach(&ring); 182 return (result); 183} 184