1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include <isc/app.h>
16 #include <isc/base64.h>
17 #include <isc/hash.h>
18 #include <isc/log.h>
19 #include <isc/managers.h>
20 #include <isc/mem.h>
21 #include <isc/netmgr.h>
22 #include <isc/nonce.h>
23 #include <isc/print.h>
24 #include <isc/random.h>
25 #include <isc/result.h>
26 #include <isc/sockaddr.h>
27 #include <isc/task.h>
28 #include <isc/util.h>
29
30 #include <dns/dispatch.h>
31 #include <dns/fixedname.h>
32 #include <dns/keyvalues.h>
33 #include <dns/message.h>
34 #include <dns/name.h>
35 #include <dns/request.h>
36 #include <dns/result.h>
37 #include <dns/tkey.h>
38 #include <dns/tsig.h>
39 #include <dns/view.h>
40
41 #define CHECK(str, x) \
42 { \
43 if ((x) != ISC_R_SUCCESS) { \
44 fprintf(stderr, "I:%s: %s\n", (str), \
45 isc_result_totext(x)); \
46 exit(-1); \
47 } \
48 }
49
50 #define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
51
52 #define TIMEOUT 30
53
54 static char *ip_address = NULL;
55 static int port = 0;
56
57 static dst_key_t *ourkey = NULL;
58 static isc_mem_t *mctx = NULL;
59 static dns_tsigkey_t *tsigkey = NULL, *initialkey = NULL;
60 static dns_tsig_keyring_t *ring = NULL;
61 static unsigned char noncedata[16];
62 static isc_buffer_t nonce;
63 static dns_requestmgr_t *requestmgr = NULL;
64 static const char *ownername_str = ".";
65
66 static void
recvquery(isc_task_t * task,isc_event_t * event)67 recvquery(isc_task_t *task, isc_event_t *event) {
68 dns_requestevent_t *reqev = (dns_requestevent_t *)event;
69 isc_result_t result;
70 dns_message_t *query = NULL, *response = NULL;
71 char keyname[256];
72 isc_buffer_t keynamebuf;
73 int type;
74
75 UNUSED(task);
76
77 REQUIRE(reqev != NULL);
78
79 if (reqev->result != ISC_R_SUCCESS) {
80 fprintf(stderr, "I:request event result: %s\n",
81 isc_result_totext(reqev->result));
82 exit(-1);
83 }
84
85 query = reqev->ev_arg;
86
87 dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
88
89 result = dns_request_getresponse(reqev->request, response,
90 DNS_MESSAGEPARSE_PRESERVEORDER);
91 CHECK("dns_request_getresponse", result);
92
93 if (response->rcode != dns_rcode_noerror) {
94 result = dns_result_fromrcode(response->rcode);
95 fprintf(stderr, "I:response rcode: %s\n",
96 isc_result_totext(result));
97 exit(-1);
98 }
99
100 result = dns_tkey_processdhresponse(query, response, ourkey, &nonce,
101 &tsigkey, ring);
102 CHECK("dns_tkey_processdhresponse", result);
103
104 /*
105 * Yes, this is a hack.
106 */
107 isc_buffer_init(&keynamebuf, keyname, sizeof(keyname));
108 result = dst_key_buildfilename(tsigkey->key, 0, "", &keynamebuf);
109 CHECK("dst_key_buildfilename", result);
110 printf("%.*s\n", (int)isc_buffer_usedlength(&keynamebuf),
111 (char *)isc_buffer_base(&keynamebuf));
112 type = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_KEY;
113 result = dst_key_tofile(tsigkey->key, type, "");
114 CHECK("dst_key_tofile", result);
115
116 dns_message_detach(&query);
117 dns_message_detach(&response);
118 dns_request_destroy(&reqev->request);
119 isc_event_free(&event);
120 isc_app_shutdown();
121 return;
122 }
123
124 static void
sendquery(isc_task_t * task,isc_event_t * event)125 sendquery(isc_task_t *task, isc_event_t *event) {
126 struct in_addr inaddr;
127 isc_sockaddr_t address;
128 isc_region_t r;
129 isc_result_t result;
130 dns_fixedname_t keyname;
131 dns_fixedname_t ownername;
132 isc_buffer_t namestr, keybuf;
133 unsigned char keydata[9];
134 dns_message_t *query = NULL;
135 dns_request_t *request = NULL;
136 static char keystr[] = "0123456789ab";
137
138 isc_event_free(&event);
139
140 result = ISC_R_FAILURE;
141 if (inet_pton(AF_INET, ip_address, &inaddr) != 1) {
142 CHECK("inet_pton", result);
143 }
144 isc_sockaddr_fromin(&address, &inaddr, port);
145
146 dns_fixedname_init(&keyname);
147 isc_buffer_constinit(&namestr, "tkeytest.", 9);
148 isc_buffer_add(&namestr, 9);
149 result = dns_name_fromtext(dns_fixedname_name(&keyname), &namestr, NULL,
150 0, NULL);
151 CHECK("dns_name_fromtext", result);
152
153 dns_fixedname_init(&ownername);
154 isc_buffer_constinit(&namestr, ownername_str, strlen(ownername_str));
155 isc_buffer_add(&namestr, strlen(ownername_str));
156 result = dns_name_fromtext(dns_fixedname_name(&ownername), &namestr,
157 NULL, 0, NULL);
158 CHECK("dns_name_fromtext", result);
159
160 isc_buffer_init(&keybuf, keydata, 9);
161 result = isc_base64_decodestring(keystr, &keybuf);
162 CHECK("isc_base64_decodestring", result);
163
164 isc_buffer_usedregion(&keybuf, &r);
165
166 result = dns_tsigkey_create(
167 dns_fixedname_name(&keyname), DNS_TSIG_HMACMD5_NAME,
168 isc_buffer_base(&keybuf), isc_buffer_usedlength(&keybuf), false,
169 NULL, 0, 0, mctx, ring, &initialkey);
170 CHECK("dns_tsigkey_create", result);
171
172 dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
173
174 result = dns_tkey_builddhquery(query, ourkey,
175 dns_fixedname_name(&ownername),
176 DNS_TSIG_HMACMD5_NAME, &nonce, 3600);
177 CHECK("dns_tkey_builddhquery", result);
178
179 result = dns_request_create(requestmgr, query, &address,
180 DNS_REQUESTOPT_TCP, initialkey, TIMEOUT,
181 task, recvquery, query, &request);
182 CHECK("dns_request_create", result);
183 }
184
185 int
main(int argc,char * argv[])186 main(int argc, char *argv[]) {
187 char *ourkeyname = NULL;
188 isc_nm_t *netmgr = NULL;
189 isc_taskmgr_t *taskmgr = NULL;
190 isc_sockaddr_t bind_any;
191 dns_dispatchmgr_t *dispatchmgr = NULL;
192 dns_dispatch_t *dispatchv4 = NULL;
193 dns_view_t *view = NULL;
194 dns_tkeyctx_t *tctx = NULL;
195 isc_log_t *log = NULL;
196 isc_logconfig_t *logconfig = NULL;
197 isc_task_t *task = NULL;
198 isc_result_t result;
199 int type;
200
201 RUNCHECK(isc_app_start());
202
203 if (argc < 4) {
204 fprintf(stderr, "I:no DH key provided\n");
205 exit(-1);
206 }
207 ip_address = argv[1];
208 port = atoi(argv[2]);
209 ourkeyname = argv[3];
210
211 if (argc >= 5) {
212 ownername_str = argv[4];
213 }
214
215 isc_mem_debugging = ISC_MEM_DEBUGRECORD;
216 isc_mem_create(&mctx);
217
218 isc_log_create(mctx, &log, &logconfig);
219
220 RUNCHECK(dst_lib_init(mctx, NULL));
221
222 isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, NULL, NULL);
223
224 RUNCHECK(isc_task_create(taskmgr, 0, &task));
225 RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
226
227 isc_sockaddr_any(&bind_any);
228 RUNCHECK(dns_dispatch_createudp(dispatchmgr, &bind_any, &dispatchv4));
229 RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4,
230 NULL, &requestmgr));
231
232 RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
233 RUNCHECK(dns_tkeyctx_create(mctx, &tctx));
234
235 RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
236 dns_view_setkeyring(view, ring);
237 dns_tsigkeyring_detach(&ring);
238
239 RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL));
240
241 type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
242 result = dst_key_fromnamedfile(ourkeyname, NULL, type, mctx, &ourkey);
243 CHECK("dst_key_fromnamedfile", result);
244
245 isc_buffer_init(&nonce, noncedata, sizeof(noncedata));
246 isc_nonce_buf(noncedata, sizeof(noncedata));
247 isc_buffer_add(&nonce, sizeof(noncedata));
248
249 (void)isc_app_run();
250
251 dns_requestmgr_shutdown(requestmgr);
252 dns_requestmgr_detach(&requestmgr);
253 dns_dispatch_detach(&dispatchv4);
254 dns_dispatchmgr_detach(&dispatchmgr);
255 isc_task_shutdown(task);
256 isc_task_detach(&task);
257 isc_managers_destroy(&netmgr, &taskmgr, NULL, NULL);
258
259 dst_key_free(&ourkey);
260 dns_tsigkey_detach(&initialkey);
261 dns_tsigkey_detach(&tsigkey);
262
263 dns_tkeyctx_destroy(&tctx);
264
265 dns_view_detach(&view);
266
267 isc_log_destroy(&log);
268
269 dst_lib_destroy();
270
271 isc_mem_destroy(&mctx);
272
273 isc_app_finish();
274
275 return (0);
276 }
277