f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson/*
ff2d95be3d5e0350c5b457582cdb08869fc17789Tinderbox User * Copyright (C) 1999-2001, 2004-2007, 2009, 2011, 2012, 2016, 2017 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson */
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
135bcc2e42a94543f11af2a4196b13552ab46d89Automatic Updater/* $Id: tsigconf.c,v 1.35 2011/01/11 23:47:12 tbox Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*! \file */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson#include <config.h>
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson#include <isc/base64.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/buffer.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/mem.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/string.h>
f44202ab640d22e17b4c74bdad7817622918bd27Mark Andrews#include <isc/util.h>
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington#include <isccfg/cfg.h>
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <dns/tsig.h>
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington#include <dns/result.h>
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
7dde2780aeae0da4e965d823578a604d8ce1215fAndreas Gustafsson#include <named/log.h>
7dde2780aeae0da4e965d823578a604d8ce1215fAndreas Gustafsson
f5862b6f22761d83c230e17f7d443211df19e52cBrian Wellington#include <named/config.h>
9259fed3d8ac5d1efa9b5a647969e40c9c934484Andreas Gustafsson#include <named/tsigconf.h>
9259fed3d8ac5d1efa9b5a647969e40c9c934484Andreas Gustafsson
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafssonstatic isc_result_t
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrewsadd_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring,
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews isc_mem_t *mctx)
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews{
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dns_tsigkey_t *tsigkey = NULL;
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const cfg_listelt_t *element;
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const cfg_obj_t *key = NULL;
4e1d3e67cdc76609bad5f0310ac48de10b442b9fMark Andrews const char *keyid = NULL;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson unsigned char *secret = NULL;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson int secretalloc = 0;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson int secretlen = 0;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson isc_result_t ret;
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellington isc_stdtime_t now;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews isc_uint16_t bits;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington for (element = cfg_list_first(list);
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington element != NULL;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington element = cfg_list_next(element))
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington {
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const cfg_obj_t *algobj = NULL;
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const cfg_obj_t *secretobj = NULL;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson dns_name_t keyname;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington dns_name_t *alg;
4e1d3e67cdc76609bad5f0310ac48de10b442b9fMark Andrews const char *algstr;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington char keynamedata[1024];
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington isc_buffer_t keynamesrc, keynamebuf;
4e1d3e67cdc76609bad5f0310ac48de10b442b9fMark Andrews const char *secretstr;
9df7d74e421cf715c6e3cbbad2aba6d33a5d1c9bBrian Wellington isc_buffer_t secretbuf;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington key = cfg_listelt_value(element);
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington keyid = cfg_obj_asstring(cfg_map_getname(key));
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington algobj = NULL;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington secretobj = NULL;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington (void)cfg_map_get(key, "algorithm", &algobj);
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington (void)cfg_map_get(key, "secret", &secretobj);
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington INSIST(algobj != NULL && secretobj != NULL);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Create the key name.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington dns_name_init(&keyname, NULL);
6f7abb89ec22aef5eda40ed60fcf605a42b78d4dMark Andrews isc_buffer_constinit(&keynamesrc, keyid, strlen(keyid));
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington isc_buffer_add(&keynamesrc, strlen(keyid));
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata));
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname,
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 DNS_NAME_DOWNCASE, &keynamebuf);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson if (ret != ISC_R_SUCCESS)
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson goto failure;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Create the algorithm.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
fb64c9cf757422c5473764521ffc7c6111b8c821Brian Wellington algstr = cfg_obj_asstring(algobj);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if (ns_config_getkeyalgorithm(algstr, &alg, &bits)
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews != ISC_R_SUCCESS) {
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews "key '%s': has a unsupported algorithm '%s'",
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews keyid, algstr);
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington ret = DNS_R_BADALG;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington goto failure;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson }
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington secretstr = cfg_obj_asstring(secretobj);
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington secretalloc = secretlen = strlen(secretstr) * 3 / 4;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson secret = isc_mem_get(mctx, secretlen);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson if (secret == NULL) {
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson ret = ISC_R_NOMEMORY;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson goto failure;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson }
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&secretbuf, secret, secretlen);
734ae1f7c6abafe1f1ca164aad7a3dd01ee82cbdBrian Wellington ret = isc_base64_decodestring(secretstr, &secretbuf);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson if (ret != ISC_R_SUCCESS)
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson goto failure;
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence secretlen = isc_buffer_usedlength(&secretbuf);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellington isc_stdtime_get(&now);
7a184cd4e5a54a4e530f9bff8a4e46be392d0b52Brian Wellington ret = dns_tsigkey_create(&keyname, alg, secret, secretlen,
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellington ISC_FALSE, NULL, now, now,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews mctx, ring, &tsigkey);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson isc_mem_put(mctx, secret, secretalloc);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson secret = NULL;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson if (ret != ISC_R_SUCCESS)
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson goto failure;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews /*
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews * Set digest bits.
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews */
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dst_key_setbits(tsigkey->key, bits);
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews dns_tsigkey_detach(&tsigkey);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson }
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson return (ISC_R_SUCCESS);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington failure:
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
26a5f97dd8770ced729025488091b77d8beb0ab6Brian Wellington "configuring key '%s': %s", keyid,
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington isc_result_totext(ret));
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson if (secret != NULL)
9df7d74e421cf715c6e3cbbad2aba6d33a5d1c9bBrian Wellington isc_mem_put(mctx, secret, secretalloc);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson return (ret);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson}
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafssonisc_result_t
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrewsns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington isc_mem_t *mctx, dns_tsig_keyring_t **ringp)
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson{
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const cfg_obj_t *maps[3];
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews const cfg_obj_t *keylist;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson dns_tsig_keyring_t *ring = NULL;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson isc_result_t result;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington int i;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt REQUIRE(ringp != NULL && *ringp == NULL);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington i = 0;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington if (config != NULL)
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington maps[i++] = config;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington if (vconfig != NULL)
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington maps[i++] = cfg_tuple_get(vconfig, "options");
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington maps[i] = NULL;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson result = dns_tsigkeyring_create(mctx, &ring);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson if (result != ISC_R_SUCCESS)
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson return (result);
c885fad9b8bf204ae9e62c9acb0321e2bcca30a4Andreas Gustafsson
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington for (i = 0; ; i++) {
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington if (maps[i] == NULL)
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington break;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence keylist = NULL;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington result = cfg_map_get(maps[i], "key", &keylist);
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington if (result != ISC_R_SUCCESS)
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington continue;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington result = add_initial_keys(keylist, ring, mctx);
8c7eaac6bbcc9746afe8f57b60bb964745c01eafAndreas Gustafsson if (result != ISC_R_SUCCESS)
8c7eaac6bbcc9746afe8f57b60bb964745c01eafAndreas Gustafsson goto failure;
8c7eaac6bbcc9746afe8f57b60bb964745c01eafAndreas Gustafsson }
c885fad9b8bf204ae9e62c9acb0321e2bcca30a4Andreas Gustafsson
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson *ringp = ring;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson return (ISC_R_SUCCESS);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson failure:
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews dns_tsigkeyring_detach(&ring);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson return (result);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson}