tsigconf.c revision 165071
1135446Strhodes/*
2165071Sdougb * Copyright (C) 2004, 2006  Internet Systems Consortium, Inc. ("ISC")
3135446Strhodes * Copyright (C) 1999-2001  Internet Software Consortium.
4135446Strhodes *
5135446Strhodes * Permission to use, copy, modify, and 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
18165071Sdougb/* $Id: tsigconf.c,v 1.21.208.6 2006/03/02 00:37:20 marka Exp $ */
19135446Strhodes
20135446Strhodes#include <config.h>
21135446Strhodes
22135446Strhodes#include <isc/base64.h>
23135446Strhodes#include <isc/buffer.h>
24135446Strhodes#include <isc/mem.h>
25135446Strhodes#include <isc/string.h>
26135446Strhodes
27135446Strhodes#include <isccfg/cfg.h>
28135446Strhodes
29135446Strhodes#include <dns/tsig.h>
30135446Strhodes#include <dns/result.h>
31135446Strhodes
32135446Strhodes#include <named/log.h>
33135446Strhodes
34135446Strhodes#include <named/config.h>
35135446Strhodes#include <named/tsigconf.h>
36135446Strhodes
37135446Strhodesstatic isc_result_t
38165071Sdougbadd_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring,
39165071Sdougb		 isc_mem_t *mctx)
40165071Sdougb{
41165071Sdougb	const cfg_listelt_t *element;
42165071Sdougb	const cfg_obj_t *key = NULL;
43165071Sdougb	const char *keyid = NULL;
44135446Strhodes	unsigned char *secret = NULL;
45135446Strhodes	int secretalloc = 0;
46135446Strhodes	int secretlen = 0;
47135446Strhodes	isc_result_t ret;
48135446Strhodes	isc_stdtime_t now;
49135446Strhodes
50135446Strhodes	for (element = cfg_list_first(list);
51135446Strhodes	     element != NULL;
52135446Strhodes	     element = cfg_list_next(element))
53135446Strhodes	{
54165071Sdougb		const cfg_obj_t *algobj = NULL;
55165071Sdougb		const cfg_obj_t *secretobj = NULL;
56135446Strhodes		dns_name_t keyname;
57135446Strhodes		dns_name_t *alg;
58165071Sdougb		const char *algstr;
59135446Strhodes		char keynamedata[1024];
60135446Strhodes		isc_buffer_t keynamesrc, keynamebuf;
61165071Sdougb		const char *secretstr;
62135446Strhodes		isc_buffer_t secretbuf;
63135446Strhodes
64135446Strhodes		key = cfg_listelt_value(element);
65135446Strhodes		keyid = cfg_obj_asstring(cfg_map_getname(key));
66135446Strhodes
67135446Strhodes		algobj = NULL;
68135446Strhodes		secretobj = NULL;
69135446Strhodes		(void)cfg_map_get(key, "algorithm", &algobj);
70135446Strhodes		(void)cfg_map_get(key, "secret", &secretobj);
71135446Strhodes		INSIST(algobj != NULL && secretobj != NULL);
72135446Strhodes
73135446Strhodes		/*
74135446Strhodes		 * Create the key name.
75135446Strhodes		 */
76135446Strhodes		dns_name_init(&keyname, NULL);
77135446Strhodes		isc_buffer_init(&keynamesrc, keyid, strlen(keyid));
78135446Strhodes		isc_buffer_add(&keynamesrc, strlen(keyid));
79135446Strhodes		isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata));
80135446Strhodes		ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname,
81135446Strhodes					ISC_TRUE, &keynamebuf);
82135446Strhodes		if (ret != ISC_R_SUCCESS)
83135446Strhodes			goto failure;
84135446Strhodes
85135446Strhodes		/*
86135446Strhodes		 * Create the algorithm.
87135446Strhodes		 */
88135446Strhodes		algstr = cfg_obj_asstring(algobj);
89135446Strhodes		if (ns_config_getkeyalgorithm(algstr, &alg) != ISC_R_SUCCESS) {
90135446Strhodes			cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR,
91135446Strhodes				    "key '%s': the only supported algorithm "
92135446Strhodes				    "is hmac-md5", keyid);
93135446Strhodes			ret = DNS_R_BADALG;
94135446Strhodes			goto failure;
95135446Strhodes		}
96135446Strhodes
97135446Strhodes		secretstr = cfg_obj_asstring(secretobj);
98135446Strhodes		secretalloc = secretlen = strlen(secretstr) * 3 / 4;
99135446Strhodes		secret = isc_mem_get(mctx, secretlen);
100135446Strhodes		if (secret == NULL) {
101135446Strhodes			ret = ISC_R_NOMEMORY;
102135446Strhodes			goto failure;
103135446Strhodes		}
104135446Strhodes		isc_buffer_init(&secretbuf, secret, secretlen);
105135446Strhodes		ret = isc_base64_decodestring(secretstr, &secretbuf);
106135446Strhodes		if (ret != ISC_R_SUCCESS)
107135446Strhodes			goto failure;
108135446Strhodes		secretlen = isc_buffer_usedlength(&secretbuf);
109135446Strhodes
110135446Strhodes		isc_stdtime_get(&now);
111135446Strhodes		ret = dns_tsigkey_create(&keyname, alg, secret, secretlen,
112135446Strhodes					 ISC_FALSE, NULL, now, now,
113135446Strhodes					 mctx, ring, NULL);
114135446Strhodes		isc_mem_put(mctx, secret, secretalloc);
115135446Strhodes		secret = NULL;
116135446Strhodes		if (ret != ISC_R_SUCCESS)
117135446Strhodes			goto failure;
118135446Strhodes	}
119135446Strhodes
120135446Strhodes	return (ISC_R_SUCCESS);
121135446Strhodes
122135446Strhodes failure:
123135446Strhodes	cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
124135446Strhodes		    "configuring key '%s': %s", keyid,
125135446Strhodes		    isc_result_totext(ret));
126135446Strhodes
127135446Strhodes	if (secret != NULL)
128135446Strhodes		isc_mem_put(mctx, secret, secretalloc);
129135446Strhodes	return (ret);
130135446Strhodes
131135446Strhodes}
132135446Strhodes
133135446Strhodesisc_result_t
134165071Sdougbns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
135135446Strhodes			  isc_mem_t *mctx, dns_tsig_keyring_t **ringp)
136135446Strhodes{
137165071Sdougb	const cfg_obj_t *maps[3];
138165071Sdougb	const cfg_obj_t *keylist;
139135446Strhodes	dns_tsig_keyring_t *ring = NULL;
140135446Strhodes	isc_result_t result;
141135446Strhodes	int i;
142135446Strhodes
143135446Strhodes	i = 0;
144135446Strhodes	if (config != NULL)
145135446Strhodes		maps[i++] = config;
146135446Strhodes	if (vconfig != NULL)
147135446Strhodes		maps[i++] = cfg_tuple_get(vconfig, "options");
148135446Strhodes	maps[i] = NULL;
149135446Strhodes
150135446Strhodes	result = dns_tsigkeyring_create(mctx, &ring);
151135446Strhodes	if (result != ISC_R_SUCCESS)
152135446Strhodes		return (result);
153135446Strhodes
154135446Strhodes	for (i = 0; ; i++) {
155135446Strhodes		if (maps[i] == NULL)
156135446Strhodes			break;
157135446Strhodes		keylist = NULL;
158135446Strhodes		result = cfg_map_get(maps[i], "key", &keylist);
159135446Strhodes		if (result != ISC_R_SUCCESS)
160135446Strhodes			continue;
161135446Strhodes		result = add_initial_keys(keylist, ring, mctx);
162135446Strhodes		if (result != ISC_R_SUCCESS)
163135446Strhodes			goto failure;
164135446Strhodes	}
165135446Strhodes
166135446Strhodes	*ringp = ring;
167135446Strhodes	return (ISC_R_SUCCESS);
168135446Strhodes
169135446Strhodes failure:
170135446Strhodes	dns_tsigkeyring_destroy(&ring);
171135446Strhodes	return (result);
172135446Strhodes}
173