tsigconf.c revision f44202ab640d22e17b4c74bdad7817622918bd27
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson/*
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 1999-2001, 2004-2007, 2009, 2011, 2012, 2016 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson * This Source Code Form is subject to the terms of the Mozilla Public
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson * License, v. 2.0. If a copy of the MPL was not distributed with this
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson * file, You can obtain one at http://mozilla.org/MPL/2.0/.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence */
15a44745412679c30a6d022733925af70a38b715David Lawrence
15a44745412679c30a6d022733925af70a38b715David Lawrence/* $Id: tsigconf.c,v 1.35 2011/01/11 23:47:12 tbox Exp $ */
15a44745412679c30a6d022733925af70a38b715David Lawrence
15a44745412679c30a6d022733925af70a38b715David Lawrence/*! \file */
15a44745412679c30a6d022733925af70a38b715David Lawrence
15a44745412679c30a6d022733925af70a38b715David Lawrence#include <config.h>
15a44745412679c30a6d022733925af70a38b715David Lawrence
15a44745412679c30a6d022733925af70a38b715David Lawrence#include <isc/base64.h>
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson#include <isc/buffer.h>
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson#include <isc/mem.h>
593cb00bd17e5e2ab0dcb7c635a9a81082dc5d0eAndreas Gustafsson#include <isc/string.h>
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence#include <isc/util.h>
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson#include <isccfg/cfg.h>
593cb00bd17e5e2ab0dcb7c635a9a81082dc5d0eAndreas Gustafsson
593cb00bd17e5e2ab0dcb7c635a9a81082dc5d0eAndreas Gustafsson#include <dns/tsig.h>
3e14b69d196a3ebeecc4662c426344dcfd7db678Andreas Gustafsson#include <dns/result.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
d8e34837cd6c88c42b3ecdb9107a43ecf8252e79David Lawrence#include <named/log.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
364a82f7c25b62967678027043425201a5e5171aBob Halley#include <named/config.h>
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson#include <named/tsigconf.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencestatic isc_result_t
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafssonadd_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring,
3e14b69d196a3ebeecc4662c426344dcfd7db678Andreas Gustafsson isc_mem_t *mctx)
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence{
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson dns_tsigkey_t *tsigkey = NULL;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson const cfg_listelt_t *element;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson const cfg_obj_t *key = NULL;
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence const char *keyid = NULL;
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence unsigned char *secret = NULL;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson int secretalloc = 0;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson int secretlen = 0;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_result_t ret;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_stdtime_t now;
600cfa2ba4c50017581b6c14e3a688a82ecebbe0David Lawrence isc_uint16_t bits;
600cfa2ba4c50017581b6c14e3a688a82ecebbe0David Lawrence
600cfa2ba4c50017581b6c14e3a688a82ecebbe0David Lawrence for (element = cfg_list_first(list);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson element != NULL;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson element = cfg_list_next(element))
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson {
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson const cfg_obj_t *algobj = NULL;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson const cfg_obj_t *secretobj = NULL;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson dns_name_t keyname;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson dns_name_t *alg;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson const char *algstr;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson char keynamedata[1024];
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_buffer_t keynamesrc, keynamebuf;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson const char *secretstr;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_buffer_t secretbuf;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson key = cfg_listelt_value(element);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson keyid = cfg_obj_asstring(cfg_map_getname(key));
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson algobj = NULL;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence secretobj = NULL;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson (void)cfg_map_get(key, "algorithm", &algobj);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson (void)cfg_map_get(key, "secret", &secretobj);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson INSIST(algobj != NULL && secretobj != NULL);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence /*
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson * Create the key name.
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence dns_name_init(&keyname, NULL);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_buffer_constinit(&keynamesrc, keyid, strlen(keyid));
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_buffer_add(&keynamesrc, strlen(keyid));
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata));
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence DNS_NAME_DOWNCASE, &keynamebuf);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson if (ret != ISC_R_SUCCESS)
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence goto failure;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson /*
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson * Create the algorithm.
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson */
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson algstr = cfg_obj_asstring(algobj);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson if (ns_config_getkeyalgorithm(algstr, &alg, &bits)
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson != ISC_R_SUCCESS) {
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR,
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson "key '%s': has a unsupported algorithm '%s'",
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson keyid, algstr);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson ret = DNS_R_BADALG;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson goto failure;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson }
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson secretstr = cfg_obj_asstring(secretobj);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson secretalloc = secretlen = strlen(secretstr) * 3 / 4;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson secret = isc_mem_get(mctx, secretlen);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson if (secret == NULL) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence ret = ISC_R_NOMEMORY;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson goto failure;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson }
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_buffer_init(&secretbuf, secret, secretlen);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson ret = isc_base64_decodestring(secretstr, &secretbuf);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson if (ret != ISC_R_SUCCESS)
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson goto failure;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence secretlen = isc_buffer_usedlength(&secretbuf);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_stdtime_get(&now);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson ret = dns_tsigkey_create(&keyname, alg, secret, secretlen,
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson ISC_FALSE, NULL, now, now,
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson mctx, ring, &tsigkey);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_mem_put(mctx, secret, secretalloc);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson secret = NULL;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson if (ret != ISC_R_SUCCESS)
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson goto failure;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson /*
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson * Set digest bits.
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson */
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson dst_key_setbits(tsigkey->key, bits);
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson dns_tsigkey_detach(&tsigkey);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson }
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson return (ISC_R_SUCCESS);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson failure:
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson "configuring key '%s': %s", keyid,
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_result_totext(ret));
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson if (secret != NULL)
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_mem_put(mctx, secret, secretalloc);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence return (ret);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson}
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafssonisc_result_t
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafssonns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson isc_mem_t *mctx, dns_tsig_keyring_t **ringp)
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson{
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson const cfg_obj_t *maps[3];
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson const cfg_obj_t *keylist;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson dns_tsig_keyring_t *ring = NULL;
7bf91d95eb5a49117d5080bbd03839b9de5c8423Andreas Gustafsson isc_result_t result;
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington int i;
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington REQUIRE(ringp != NULL && *ringp == NULL);
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington
7bf91d95eb5a49117d5080bbd03839b9de5c8423Andreas Gustafsson i = 0;
7bf91d95eb5a49117d5080bbd03839b9de5c8423Andreas Gustafsson if (config != NULL)
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington maps[i++] = config;
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington if (vconfig != NULL)
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington maps[i++] = cfg_tuple_get(vconfig, "options");
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington maps[i] = NULL;
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington result = dns_tsigkeyring_create(mctx, &ring);
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington if (result != ISC_R_SUCCESS)
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington return (result);
19f4d25fd5b35b1375b0b9f13b66770ee4a66154Brian Wellington
7bf91d95eb5a49117d5080bbd03839b9de5c8423Andreas Gustafsson for (i = 0; ; i++) {
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson if (maps[i] == NULL)
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson break;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson keylist = NULL;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson result = cfg_map_get(maps[i], "key", &keylist);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson if (result != ISC_R_SUCCESS)
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence continue;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson result = add_initial_keys(keylist, ring, mctx);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson if (result != ISC_R_SUCCESS)
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson goto failure;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson }
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson *ringp = ring;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson return (ISC_R_SUCCESS);
68e4926b2262571e004b4be00b905ec776c01d9cMichael Graff
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson failure:
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson dns_tsigkeyring_detach(&ring);
68e4926b2262571e004b4be00b905ec776c01d9cMichael Graff return (result);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson}
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson