1/* 2 * Copyright (C) 2004, 2005, 2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 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: keycreate.c,v 1.20 2011/01/11 23:47:13 tbox Exp $ */ 19 20#include <config.h> 21 22#include <stdlib.h> 23#include <string.h> 24 25#include <isc/app.h> 26#include <isc/base64.h> 27#include <isc/entropy.h> 28#include <isc/hash.h> 29#include <isc/log.h> 30#include <isc/mem.h> 31#include <isc/sockaddr.h> 32#include <isc/socket.h> 33#include <isc/task.h> 34#include <isc/timer.h> 35#include <isc/util.h> 36 37#include <dns/dispatch.h> 38#include <dns/fixedname.h> 39#include <dns/keyvalues.h> 40#include <dns/message.h> 41#include <dns/name.h> 42#include <dns/request.h> 43#include <dns/result.h> 44#include <dns/tkey.h> 45#include <dns/tsig.h> 46#include <dns/view.h> 47 48#include <dst/result.h> 49 50#define CHECK(str, x) { \ 51 if ((x) != ISC_R_SUCCESS) { \ 52 fprintf(stderr, "I:%s: %s\n", (str), isc_result_totext(x)); \ 53 exit(-1); \ 54 } \ 55} 56 57#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS) 58 59#define PORT 5300 60#define TIMEOUT 30 61 62static dst_key_t *ourkey; 63static isc_mem_t *mctx; 64static dns_tsigkey_t *tsigkey, *initialkey; 65static dns_tsig_keyring_t *ring; 66static unsigned char noncedata[16]; 67static isc_buffer_t nonce; 68static dns_requestmgr_t *requestmgr; 69static const char *ownername_str = "."; 70 71static void 72recvquery(isc_task_t *task, isc_event_t *event) { 73 dns_requestevent_t *reqev = (dns_requestevent_t *)event; 74 isc_result_t result; 75 dns_message_t *query, *response; 76 char keyname[256]; 77 isc_buffer_t keynamebuf; 78 int type; 79 80 UNUSED(task); 81 82 REQUIRE(reqev != NULL); 83 84 if (reqev->result != ISC_R_SUCCESS) { 85 fprintf(stderr, "I:request event result: %s\n", 86 isc_result_totext(reqev->result)); 87 exit(-1); 88 } 89 90 query = reqev->ev_arg; 91 92 response = NULL; 93 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); 94 CHECK("dns_message_create", result); 95 96 result = dns_request_getresponse(reqev->request, response, 97 DNS_MESSAGEPARSE_PRESERVEORDER); 98 CHECK("dns_request_getresponse", result); 99 100 if (response->rcode != dns_rcode_noerror) { 101 result = ISC_RESULTCLASS_DNSRCODE + response->rcode; 102 fprintf(stderr, "I:response rcode: %s\n", 103 isc_result_totext(result)); 104 exit(-1); 105 } 106 107 result = dns_tkey_processdhresponse(query, response, ourkey, &nonce, 108 &tsigkey, ring); 109 CHECK("dns_tkey_processdhresponse", result); 110 111 /* 112 * Yes, this is a hack. 113 */ 114 isc_buffer_init(&keynamebuf, keyname, sizeof(keyname)); 115 result = dst_key_buildfilename(tsigkey->key, 0, "", &keynamebuf); 116 CHECK("dst_key_buildfilename", result); 117 printf("%.*s\n", (int)isc_buffer_usedlength(&keynamebuf), 118 (char *)isc_buffer_base(&keynamebuf)); 119 type = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_KEY; 120 result = dst_key_tofile(tsigkey->key, type, ""); 121 CHECK("dst_key_tofile", result); 122 123 dns_message_destroy(&query); 124 dns_message_destroy(&response); 125 dns_request_destroy(&reqev->request); 126 isc_event_free(&event); 127 isc_app_shutdown(); 128 return; 129} 130 131static void 132sendquery(isc_task_t *task, isc_event_t *event) { 133 struct in_addr inaddr; 134 isc_sockaddr_t address; 135 isc_region_t r; 136 isc_result_t result; 137 dns_fixedname_t keyname; 138 dns_fixedname_t ownername; 139 isc_buffer_t namestr, keybuf; 140 unsigned char keydata[9]; 141 dns_message_t *query; 142 dns_request_t *request; 143 static char keystr[] = "0123456789ab"; 144 145 isc_event_free(&event); 146 147 result = ISC_R_FAILURE; 148 if (inet_pton(AF_INET, "10.53.0.1", &inaddr) != 1) 149 CHECK("inet_pton", result); 150 isc_sockaddr_fromin(&address, &inaddr, PORT); 151 152 dns_fixedname_init(&keyname); 153 isc_buffer_init(&namestr, "tkeytest.", 9); 154 isc_buffer_add(&namestr, 9); 155 result = dns_name_fromtext(dns_fixedname_name(&keyname), &namestr, 156 NULL, 0, NULL); 157 CHECK("dns_name_fromtext", result); 158 159 dns_fixedname_init(&ownername); 160 isc_buffer_init(&namestr, ownername_str, strlen(ownername_str)); 161 isc_buffer_add(&namestr, strlen(ownername_str)); 162 result = dns_name_fromtext(dns_fixedname_name(&ownername), &namestr, 163 NULL, 0, NULL); 164 CHECK("dns_name_fromtext", result); 165 166 isc_buffer_init(&keybuf, keydata, 9); 167 result = isc_base64_decodestring(keystr, &keybuf); 168 CHECK("isc_base64_decodestring", result); 169 170 isc_buffer_usedregion(&keybuf, &r); 171 172 initialkey = NULL; 173 result = dns_tsigkey_create(dns_fixedname_name(&keyname), 174 DNS_TSIG_HMACMD5_NAME, 175 isc_buffer_base(&keybuf), 176 isc_buffer_usedlength(&keybuf), 177 ISC_FALSE, NULL, 0, 0, mctx, ring, 178 &initialkey); 179 CHECK("dns_tsigkey_create", result); 180 181 query = NULL; 182 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query); 183 CHECK("dns_message_create", result); 184 185 result = dns_tkey_builddhquery(query, ourkey, 186 dns_fixedname_name(&ownername), 187 DNS_TSIG_HMACMD5_NAME, &nonce, 3600); 188 CHECK("dns_tkey_builddhquery", result); 189 190 request = NULL; 191 result = dns_request_create(requestmgr, query, &address, 192 0, initialkey, TIMEOUT, task, 193 recvquery, query, &request); 194 CHECK("dns_request_create", result); 195} 196 197int 198main(int argc, char *argv[]) { 199 char *ourkeyname; 200 isc_taskmgr_t *taskmgr; 201 isc_timermgr_t *timermgr; 202 isc_socketmgr_t *socketmgr; 203 isc_socket_t *sock; 204 unsigned int attrs, attrmask; 205 isc_sockaddr_t bind_any; 206 dns_dispatchmgr_t *dispatchmgr; 207 dns_dispatch_t *dispatchv4; 208 dns_view_t *view; 209 isc_entropy_t *ectx; 210 dns_tkeyctx_t *tctx; 211 isc_log_t *log; 212 isc_logconfig_t *logconfig; 213 isc_task_t *task; 214 isc_result_t result; 215 int type; 216 217 RUNCHECK(isc_app_start()); 218 219 if (argc < 2) { 220 fprintf(stderr, "I:no DH key provided\n"); 221 exit(-1); 222 } 223 ourkeyname = argv[1]; 224 225 if (argc >= 3) 226 ownername_str = argv[2]; 227 228 dns_result_register(); 229 230 mctx = NULL; 231 RUNCHECK(isc_mem_create(0, 0, &mctx)); 232 233 ectx = NULL; 234 RUNCHECK(isc_entropy_create(mctx, &ectx)); 235 RUNCHECK(isc_entropy_createfilesource(ectx, "random.data")); 236 RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)); 237 238 log = NULL; 239 logconfig = NULL; 240 RUNCHECK(isc_log_create(mctx, &log, &logconfig)); 241 242 RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY)); 243 244 taskmgr = NULL; 245 RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr)); 246 task = NULL; 247 RUNCHECK(isc_task_create(taskmgr, 0, &task)); 248 timermgr = NULL; 249 RUNCHECK(isc_timermgr_create(mctx, &timermgr)); 250 socketmgr = NULL; 251 RUNCHECK(isc_socketmgr_create(mctx, &socketmgr)); 252 dispatchmgr = NULL; 253 RUNCHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr)); 254 isc_sockaddr_any(&bind_any); 255 attrs = DNS_DISPATCHATTR_UDP | 256 DNS_DISPATCHATTR_MAKEQUERY | 257 DNS_DISPATCHATTR_IPV4; 258 attrmask = DNS_DISPATCHATTR_UDP | 259 DNS_DISPATCHATTR_TCP | 260 DNS_DISPATCHATTR_IPV4 | 261 DNS_DISPATCHATTR_IPV6; 262 dispatchv4 = NULL; 263 RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, 264 &bind_any, 4096, 4, 2, 3, 5, 265 attrs, attrmask, &dispatchv4)); 266 requestmgr = NULL; 267 RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, 268 dispatchmgr, dispatchv4, NULL, 269 &requestmgr)); 270 271 ring = NULL; 272 RUNCHECK(dns_tsigkeyring_create(mctx, &ring)); 273 tctx = NULL; 274 RUNCHECK(dns_tkeyctx_create(mctx, ectx, &tctx)); 275 276 view = NULL; 277 RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); 278 dns_view_setkeyring(view, ring); 279 dns_tsigkeyring_detach(&ring); 280 281 sock = NULL; 282 RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, 283 &sock)); 284 285 RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL)); 286 287 ourkey = NULL; 288 type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY; 289 result = dst_key_fromnamedfile(ourkeyname, NULL, type, mctx, &ourkey); 290 CHECK("dst_key_fromnamedfile", result); 291 292 isc_buffer_init(&nonce, noncedata, sizeof(noncedata)); 293 result = isc_entropy_getdata(ectx, noncedata, sizeof(noncedata), 294 NULL, ISC_ENTROPY_BLOCKING); 295 CHECK("isc_entropy_getdata", result); 296 isc_buffer_add(&nonce, sizeof(noncedata)); 297 298 (void)isc_app_run(); 299 300 dns_requestmgr_shutdown(requestmgr); 301 dns_requestmgr_detach(&requestmgr); 302 dns_dispatch_detach(&dispatchv4); 303 dns_dispatchmgr_destroy(&dispatchmgr); 304 isc_task_shutdown(task); 305 isc_task_detach(&task); 306 isc_taskmgr_destroy(&taskmgr); 307 isc_socket_detach(&sock); 308 isc_socketmgr_destroy(&socketmgr); 309 isc_timermgr_destroy(&timermgr); 310 311 dst_key_free(&ourkey); 312 dns_tsigkey_detach(&initialkey); 313 dns_tsigkey_detach(&tsigkey); 314 315 dns_tkeyctx_destroy(&tctx); 316 317 dns_view_detach(&view); 318 319 isc_log_destroy(&log); 320 321 dst_lib_destroy(); 322 isc_hash_destroy(); 323 isc_entropy_detach(&ectx); 324 325 isc_mem_destroy(&mctx); 326 327 isc_app_finish(); 328 329 return (0); 330} 331