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