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