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