Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / contrib / bind-9.3 / bin / named / tsigconf.c
1 /*
2  * Copyright (C) 2004, 2006  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2001  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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.21.208.6 2006/03/02 00:37:20 marka Exp $ */
19
20 #include <config.h>
21
22 #include <isc/base64.h>
23 #include <isc/buffer.h>
24 #include <isc/mem.h>
25 #include <isc/string.h>
26
27 #include <isccfg/cfg.h>
28
29 #include <dns/tsig.h>
30 #include <dns/result.h>
31
32 #include <named/log.h>
33
34 #include <named/config.h>
35 #include <named/tsigconf.h>
36
37 static isc_result_t
38 add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring,
39                  isc_mem_t *mctx)
40 {
41         const cfg_listelt_t *element;
42         const cfg_obj_t *key = NULL;
43         const char *keyid = NULL;
44         unsigned char *secret = NULL;
45         int secretalloc = 0;
46         int secretlen = 0;
47         isc_result_t ret;
48         isc_stdtime_t now;
49
50         for (element = cfg_list_first(list);
51              element != NULL;
52              element = cfg_list_next(element))
53         {
54                 const cfg_obj_t *algobj = NULL;
55                 const cfg_obj_t *secretobj = NULL;
56                 dns_name_t keyname;
57                 dns_name_t *alg;
58                 const char *algstr;
59                 char keynamedata[1024];
60                 isc_buffer_t keynamesrc, keynamebuf;
61                 const char *secretstr;
62                 isc_buffer_t secretbuf;
63
64                 key = cfg_listelt_value(element);
65                 keyid = cfg_obj_asstring(cfg_map_getname(key));
66
67                 algobj = NULL;
68                 secretobj = NULL;
69                 (void)cfg_map_get(key, "algorithm", &algobj);
70                 (void)cfg_map_get(key, "secret", &secretobj);
71                 INSIST(algobj != NULL && secretobj != NULL);
72
73                 /*
74                  * Create the key name.
75                  */
76                 dns_name_init(&keyname, NULL);
77                 isc_buffer_init(&keynamesrc, keyid, strlen(keyid));
78                 isc_buffer_add(&keynamesrc, strlen(keyid));
79                 isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata));
80                 ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname,
81                                         ISC_TRUE, &keynamebuf);
82                 if (ret != ISC_R_SUCCESS)
83                         goto failure;
84
85                 /*
86                  * Create the algorithm.
87                  */
88                 algstr = cfg_obj_asstring(algobj);
89                 if (ns_config_getkeyalgorithm(algstr, &alg) != ISC_R_SUCCESS) {
90                         cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR,
91                                     "key '%s': the only supported algorithm "
92                                     "is hmac-md5", keyid);
93                         ret = DNS_R_BADALG;
94                         goto failure;
95                 }
96
97                 secretstr = cfg_obj_asstring(secretobj);
98                 secretalloc = secretlen = strlen(secretstr) * 3 / 4;
99                 secret = isc_mem_get(mctx, secretlen);
100                 if (secret == NULL) {
101                         ret = ISC_R_NOMEMORY;
102                         goto failure;
103                 }
104                 isc_buffer_init(&secretbuf, secret, secretlen);
105                 ret = isc_base64_decodestring(secretstr, &secretbuf);
106                 if (ret != ISC_R_SUCCESS)
107                         goto failure;
108                 secretlen = isc_buffer_usedlength(&secretbuf);
109
110                 isc_stdtime_get(&now);
111                 ret = dns_tsigkey_create(&keyname, alg, secret, secretlen,
112                                          ISC_FALSE, NULL, now, now,
113                                          mctx, ring, NULL);
114                 isc_mem_put(mctx, secret, secretalloc);
115                 secret = NULL;
116                 if (ret != ISC_R_SUCCESS)
117                         goto failure;
118         }
119
120         return (ISC_R_SUCCESS);
121
122  failure:
123         cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
124                     "configuring key '%s': %s", keyid,
125                     isc_result_totext(ret));
126
127         if (secret != NULL)
128                 isc_mem_put(mctx, secret, secretalloc);
129         return (ret);
130
131 }
132
133 isc_result_t
134 ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
135                           isc_mem_t *mctx, dns_tsig_keyring_t **ringp)
136 {
137         const cfg_obj_t *maps[3];
138         const cfg_obj_t *keylist;
139         dns_tsig_keyring_t *ring = NULL;
140         isc_result_t result;
141         int i;
142
143         i = 0;
144         if (config != NULL)
145                 maps[i++] = config;
146         if (vconfig != NULL)
147                 maps[i++] = cfg_tuple_get(vconfig, "options");
148         maps[i] = NULL;
149
150         result = dns_tsigkeyring_create(mctx, &ring);
151         if (result != ISC_R_SUCCESS)
152                 return (result);
153
154         for (i = 0; ; i++) {
155                 if (maps[i] == NULL)
156                         break;
157                 keylist = NULL;
158                 result = cfg_map_get(maps[i], "key", &keylist);
159                 if (result != ISC_R_SUCCESS)
160                         continue;
161                 result = add_initial_keys(keylist, ring, mctx);
162                 if (result != ISC_R_SUCCESS)
163                         goto failure;
164         }
165
166         *ringp = ring;
167         return (ISC_R_SUCCESS);
168
169  failure:
170         dns_tsigkeyring_destroy(&ring);
171         return (result);
172 }