Home | History | Annotate | Line # | Download | only in named
tsigconf.c revision 1.3.2.2
      1 /*	$NetBSD: tsigconf.c,v 1.3.2.2 2019/06/10 22:03:00 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * This Source Code Form is subject to the terms of the Mozilla Public
      7  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9  *
     10  * See the COPYRIGHT file distributed with this work for additional
     11  * information regarding copyright ownership.
     12  */
     13 
     14 
     15 /*! \file */
     16 
     17 #include <config.h>
     18 
     19 #include <inttypes.h>
     20 
     21 #include <isc/base64.h>
     22 #include <isc/buffer.h>
     23 #include <isc/mem.h>
     24 #include <isc/string.h>
     25 #include <isc/util.h>
     26 
     27 #include <isccfg/cfg.h>
     28 
     29 #include <dns/tsig.h>
     30 #include <dns/result.h>
     31 
     32 #include <named/log.h>
     33 
     34 #include <named/config.h>
     35 #include <named/tsigconf.h>
     36 
     37 static isc_result_t
     38 add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring,
     39 		 isc_mem_t *mctx)
     40 {
     41 	dns_tsigkey_t *tsigkey = NULL;
     42 	const cfg_listelt_t *element;
     43 	const cfg_obj_t *key = NULL;
     44 	const char *keyid = NULL;
     45 	unsigned char *secret = NULL;
     46 	int secretalloc = 0;
     47 	int secretlen = 0;
     48 	isc_result_t ret;
     49 	isc_stdtime_t now;
     50 	uint16_t bits;
     51 
     52 	for (element = cfg_list_first(list);
     53 	     element != NULL;
     54 	     element = cfg_list_next(element))
     55 	{
     56 		const cfg_obj_t *algobj = NULL;
     57 		const cfg_obj_t *secretobj = NULL;
     58 		dns_name_t keyname;
     59 		const dns_name_t *alg;
     60 		const char *algstr;
     61 		char keynamedata[1024];
     62 		isc_buffer_t keynamesrc, keynamebuf;
     63 		const char *secretstr;
     64 		isc_buffer_t secretbuf;
     65 
     66 		key = cfg_listelt_value(element);
     67 		keyid = cfg_obj_asstring(cfg_map_getname(key));
     68 
     69 		algobj = NULL;
     70 		secretobj = NULL;
     71 		(void)cfg_map_get(key, "algorithm", &algobj);
     72 		(void)cfg_map_get(key, "secret", &secretobj);
     73 		INSIST(algobj != NULL && secretobj != NULL);
     74 
     75 		/*
     76 		 * Create the key name.
     77 		 */
     78 		dns_name_init(&keyname, NULL);
     79 		isc_buffer_constinit(&keynamesrc, keyid, strlen(keyid));
     80 		isc_buffer_add(&keynamesrc, strlen(keyid));
     81 		isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata));
     82 		ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname,
     83 					DNS_NAME_DOWNCASE, &keynamebuf);
     84 		if (ret != ISC_R_SUCCESS)
     85 			goto failure;
     86 
     87 		/*
     88 		 * Create the algorithm.
     89 		 */
     90 		algstr = cfg_obj_asstring(algobj);
     91 		if (named_config_getkeyalgorithm(algstr, &alg, &bits)
     92 		    != ISC_R_SUCCESS) {
     93 			cfg_obj_log(algobj, named_g_lctx, ISC_LOG_ERROR,
     94 				    "key '%s': has a "
     95 				    "unsupported algorithm '%s'",
     96 				    keyid, algstr);
     97 			ret = DNS_R_BADALG;
     98 			goto failure;
     99 		}
    100 
    101 		secretstr = cfg_obj_asstring(secretobj);
    102 		secretalloc = secretlen = strlen(secretstr) * 3 / 4;
    103 		secret = isc_mem_get(mctx, secretlen);
    104 		if (secret == NULL) {
    105 			ret = ISC_R_NOMEMORY;
    106 			goto failure;
    107 		}
    108 		isc_buffer_init(&secretbuf, secret, secretlen);
    109 		ret = isc_base64_decodestring(secretstr, &secretbuf);
    110 		if (ret != ISC_R_SUCCESS)
    111 			goto failure;
    112 		secretlen = isc_buffer_usedlength(&secretbuf);
    113 
    114 		isc_stdtime_get(&now);
    115 		ret = dns_tsigkey_create(&keyname, alg, secret, secretlen,
    116 					 false, NULL, now, now,
    117 					 mctx, ring, &tsigkey);
    118 		isc_mem_put(mctx, secret, secretalloc);
    119 		secret = NULL;
    120 		if (ret != ISC_R_SUCCESS)
    121 			goto failure;
    122 		/*
    123 		 * Set digest bits.
    124 		 */
    125 		dst_key_setbits(tsigkey->key, bits);
    126 		dns_tsigkey_detach(&tsigkey);
    127 	}
    128 
    129 	return (ISC_R_SUCCESS);
    130 
    131  failure:
    132 	cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
    133 		    "configuring key '%s': %s", keyid,
    134 		    isc_result_totext(ret));
    135 
    136 	if (secret != NULL)
    137 		isc_mem_put(mctx, secret, secretalloc);
    138 	return (ret);
    139 }
    140 
    141 isc_result_t
    142 named_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
    143 			     isc_mem_t *mctx, dns_tsig_keyring_t **ringp)
    144 {
    145 	const cfg_obj_t *maps[3];
    146 	const cfg_obj_t *keylist;
    147 	dns_tsig_keyring_t *ring = NULL;
    148 	isc_result_t result;
    149 	int i;
    150 
    151 	REQUIRE(ringp != NULL && *ringp == NULL);
    152 
    153 	i = 0;
    154 	if (config != NULL)
    155 		maps[i++] = config;
    156 	if (vconfig != NULL)
    157 		maps[i++] = cfg_tuple_get(vconfig, "options");
    158 	maps[i] = NULL;
    159 
    160 	result = dns_tsigkeyring_create(mctx, &ring);
    161 	if (result != ISC_R_SUCCESS)
    162 		return (result);
    163 
    164 	for (i = 0; ; i++) {
    165 		if (maps[i] == NULL)
    166 			break;
    167 		keylist = NULL;
    168 		result = cfg_map_get(maps[i], "key", &keylist);
    169 		if (result != ISC_R_SUCCESS)
    170 			continue;
    171 		result = add_initial_keys(keylist, ring, mctx);
    172 		if (result != ISC_R_SUCCESS)
    173 			goto failure;
    174 	}
    175 
    176 	*ringp = ring;
    177 	return (ISC_R_SUCCESS);
    178 
    179  failure:
    180 	dns_tsigkeyring_detach(&ring);
    181 	return (result);
    182 }
    183