Send TSIG signed queries with dig. This version requires all queries

from a single invocation of dig use the same key, and doesn't validate
replies yet.  Also, keys must be passed on the command line with the
-y option.  -k forthcoming.
This commit is contained in:
Michael Sawyer
2000-06-06 00:43:17 +00:00
parent 501da430e2
commit a5ed46c9fd
3 changed files with 155 additions and 23 deletions

View File

@@ -62,6 +62,8 @@ extern isc_boolean_t twiddle;
#endif
extern int exitcode;
extern isc_sockaddr_t bind_address;
extern char keynametext[MXNAME];
extern char keysecret[MXNAME];
isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE;
@@ -123,12 +125,14 @@ show_usage(void) {
"Where: domain are in the Domain Name System\n"
" q-class is one of (in,chaos,...) [default: in]\n"
" q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n"
" (Use ixfr=version for type ixfr)\n"
" q-opt is one of:\n"
" -x dot-notation (shortcut for in-addr lookups)\n"
" -f filename (batch mode)\n"
" -p port (specify port number)\n"
" -t type (specify query type)\n"
" -c class (specify query class)\n"
" -y name:key (specify named base64 tsig key)\n"
" d-opt is of the form +keyword[=value], where keyword is:\n"
" +[no]vc (TCP mode)\n"
" +[no]tcp (TCP mode, alternate syntax)\n"
@@ -184,7 +188,12 @@ received(int bytes, int frmsize, char *frm, dig_query_t *query) {
printf(";; SERVER: %.*s\n", frmsize, frm);
time (&tnow);
printf(";; WHEN: %s", ctime(&tnow));
printf (";; MSG SIZE rcvd: %d\n\n", bytes);
printf (";; MSG SIZE rcvd: %d\n", bytes);
if (keysecret[0] != 0) {
puts (";; WARNING - Not currently validating "
"TSIG signature in reply.");
}
puts ("");
} else if (query->lookup->identify && !short_form) {
diff = isc_time_microdiff(&now, &query->time_sent);
printf(";; Received %u bytes from %.*s in %d ms\n",
@@ -404,16 +413,22 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
DNS_SECTION_ADDITIONAL,
flags, buf);
check_result(result, "dns_message_sectiontotext");
result = dns_message_pseudosectiontotext(msg,
DNS_PSEUDOSECTION_TSIG,
flags, buf);
check_result(result, "dns_message_pseudosectiontotext");
result = dns_message_pseudosectiontotext(msg,
DNS_PSEUDOSECTION_SIG0,
flags, buf);
check_result(result,
"dns_message_pseudosectiontotext");
/* Only print the signature on the first record */
if (headers) {
result = dns_message_pseudosectiontotext(
msg,
DNS_PSEUDOSECTION_TSIG,
flags, buf);
check_result(result,
"dns_message_pseudosectiontotext");
result = dns_message_pseudosectiontotext(
msg,
DNS_PSEUDOSECTION_SIG0,
flags, buf);
check_result(result,
"dns_message_pseudosectiontotext");
}
}
}
if (headers && query->lookup->comments && !short_form)
@@ -499,6 +514,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
int adrs[4];
int rc;
char **rv;
char *ptr;
/*
* The semantics for parsing the args is a bit complex; if
@@ -874,6 +890,26 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
rv++;
rc--;
}
} else if (strncmp(rv[0], "-y", 2) == 0) {
if (rv[0][2] != 0)
ptr = &rv[0][2];
else {
ptr = rv[1];
rv++;
rc--;
}
ptr = strtok(ptr,":");
if (ptr == NULL) {
show_usage();
exit (exitcode);
}
strncpy(keynametext, ptr, MXNAME);
ptr = strtok(NULL, "");
if (ptr == NULL) {
show_usage();
exit (exitcode);
}
strncpy(keysecret, ptr, MXNAME);
} else if (strncmp(rv[0], "-p", 2) == 0) {
if (rv[0][2] != 0) {
port = atoi(&rv[0][2]);

View File

@@ -37,6 +37,8 @@ extern int h_errno;
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h>
#include <isc/base64.h>
#include <isc/lex.h>
#include <dns/message.h>
#include <dns/name.h>
@@ -47,6 +49,7 @@ extern int h_errno;
#include <dns/rdatalist.h>
#include <dns/result.h>
#include <dns/rdatastruct.h>
#include <dns/tsig.h>
#include <dig/dig.h>
@@ -77,6 +80,12 @@ int tries = 3;
int lookup_counter = 0;
char fixeddomain[MXNAME]="";
int exitcode = 9;
char keynametext[MXNAME];
char keysecret[MXNAME]="";
dns_name_t keyname;
dns_tsig_keyring_t *keyring=NULL;
isc_buffer_t *namebuf = NULL;
dns_tsigkey_t *key = NULL;
static void
cancel_lookup(dig_lookup_t *lookup);
@@ -327,8 +336,14 @@ setup_system(void) {
dig_searchlist_t *search;
dig_lookup_t *l;
isc_boolean_t get_servers;
isc_result_t result;
isc_buffer_t secretsrc;
isc_buffer_t secretbuf;
int secretsize;
char *secretstore;
isc_lex_t *lex = NULL;
isc_stdtime_t now;
if (fixeddomain[0]!=0) {
search = isc_mem_allocate( mctx, sizeof(struct dig_server));
if (search == NULL)
@@ -449,6 +464,65 @@ setup_system(void) {
l = ISC_LIST_NEXT(l, link) ) {
l -> origin = ISC_LIST_HEAD(search_list);
}
if (keysecret[0] != 0) {
result = dns_tsigkeyring_create(mctx, &keyring);
check_result(result, "dns_tsigkeyring_create");
result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
check_result(result, "isc_buffer_allocate");
dns_name_init(&keyname, NULL);
check_result(result, "dns_name_init");
isc_buffer_putstr(namebuf, keynametext);
secretsize = strlen(keysecret) * 3 / 4;
secretstore = isc_mem_get(mctx, secretsize);
ENSURE (secretstore != NULL);
isc_buffer_init(&secretsrc, keysecret, strlen(keysecret));
isc_buffer_add(&secretsrc, strlen(keysecret));
isc_buffer_init(&secretbuf, secretstore, secretsize);
result = isc_lex_create(mctx, strlen(keysecret), &lex);
check_result(result, "isc_lex_create");
result = isc_lex_openbuffer(lex, &secretsrc);
check_result(result, "isc_lex_openbuffer");
result = isc_base64_tobuffer(lex, &secretbuf, -1);
if (result != ISC_R_SUCCESS) {
printf (";; Couldn't create key %s: %s\n",
keynametext, isc_result_totext(result));
isc_lex_close(lex);
isc_lex_destroy(&lex);
goto SYSSETUP_FAIL;
}
secretsize = isc_buffer_usedlength(&secretbuf);
isc_lex_close(lex);
isc_lex_destroy(&lex);
isc_stdtime_get(&now);
result = dns_name_fromtext(&keyname, namebuf,
dns_rootname, ISC_FALSE,
namebuf);
if (result != ISC_R_SUCCESS) {
printf (";; Couldn't create key %s: %s\n",
keynametext, dns_result_totext(result));
goto SYSSETUP_FAIL;
}
result = dns_tsigkey_create(&keyname, dns_tsig_hmacmd5_name,
secretstore, secretsize,
ISC_TRUE, NULL, now, now, mctx,
keyring, &key);
if (result != ISC_R_SUCCESS) {
printf (";; Couldn't create key %s: %s\n",
keynametext, dns_result_totext(result));
}
isc_mem_put(mctx, secretstore, secretsize);
dns_name_invalidate(&keyname);
isc_buffer_free(&namebuf);
return;
SYSSETUP_FAIL:
isc_mem_put(mctx, secretstore, secretsize);
dns_name_invalidate(&keyname);
isc_buffer_free(&namebuf);
dns_tsigkeyring_destroy(&keyring);
return;
}
}
void
@@ -985,8 +1059,13 @@ setup_lookup(dig_lookup_t *lookup) {
if (rdtype == dns_rdatatype_ixfr)
insert_soa(lookup);
isc_buffer_init(&lookup->sendbuf, lookup->sendspace, COMMSIZE);
if (key != NULL) {
result = dns_message_settsigkey(lookup->sendmsg, key);
check_result(result, "dns_message_settsigkey");
}
debug ("Starting to render the message");
isc_buffer_init(&lookup->sendbuf, lookup->sendspace, COMMSIZE);
result = dns_message_renderbegin(lookup->sendmsg, &lookup->sendbuf);
check_result(result, "dns_message_renderbegin");
if (lookup->udpsize > 0) {
@@ -1442,6 +1521,7 @@ check_for_more_data(dig_query_t *query, dns_message_t *msg,
(rdata.type != dns_rdatatype_soa)) {
query->second_rr_rcvd = ISC_TRUE;
query->second_rr_serial = 0;
debug ("Got the second rr as nonsoa");
continue;
}
@@ -1452,18 +1532,19 @@ check_for_more_data(dig_query_t *query, dns_message_t *msg,
if (rdata.type != dns_rdatatype_soa)
goto NEXT_RDATA;
/* Now we have an SOA. Work with it. */
debug ("before tostruct");
debug ("Got a SOA");
result = dns_rdata_tostruct(&rdata,
&soa,
mctx);
check_result(result,
"dns_rdata_tostruct");
debug ("after tostruct");
if (!query->first_soa_rcvd) {
query->first_soa_rcvd =
ISC_TRUE;
query->first_rr_serial =
soa.serial;
debug ("This is the first. %d",
query->lookup->ixfr_serial);
if (query->lookup->ixfr_serial >=
soa.serial) {
dns_rdata_freestruct(&soa);
@@ -1473,6 +1554,8 @@ check_for_more_data(dig_query_t *query, dns_message_t *msg,
goto NEXT_RDATA;
}
if (!query->second_rr_rcvd) {
debug ("This is the second. %d",
query->lookup->ixfr_serial);
query->second_rr_rcvd = ISC_TRUE;
query->second_rr_serial =
soa.serial;
@@ -1485,6 +1568,7 @@ check_for_more_data(dig_query_t *query, dns_message_t *msg,
* other SOA, then this is an
* AXFR, and we're done.
*/
debug ("Done, since axfr.");
XFR_DONE:
isc_buffer_init(&b, abspace, MXNAME);
result = isc_sockaddr_totext(&sevent->
@@ -1505,16 +1589,20 @@ check_for_more_data(dig_query_t *query, dns_message_t *msg,
* IXFR and have to start really looking
* at serial numbers.
*/
if (query->second_rr_serial == soa.serial) {
if (query->first_rr_serial == soa.serial) {
debug ("Got a match for ixfr");
if (!query->first_repeat_rcvd) {
query->first_repeat_rcvd =
ISC_TRUE;
dns_rdata_freestruct(&soa);
goto NEXT_RDATA;
}
debug ("Done with ixfr");
dns_rdata_freestruct(&soa);
goto XFR_DONE;
}
debug ("Meaningless soa, %d",
soa.serial);
dns_rdata_freestruct(&soa);
NEXT_RDATA:
result = dns_rdataset_next(rdataset);
@@ -1890,13 +1978,20 @@ free_lists(int _exitcode) {
if (taskmgr != NULL)
isc_taskmgr_destroy(&taskmgr);
if (key != NULL)
dns_tsigkey_detach(&key);
if (namebuf != NULL)
isc_buffer_free(&namebuf);
if (keyring != NULL)
dns_tsigkeyring_destroy(&keyring);
#ifdef MEMDEBUG
isc_mem_stats(mctx, stderr);
#endif
isc_app_finish();
if (mctx != NULL)
isc_mem_destroy(&mctx);
isc_mem_destroy(&mctx);
debug("Getting ready to exit, code=%d",_exitcode);
if (_exitcode != 0)
exit(_exitcode);

View File

@@ -28,6 +28,7 @@ extern int h_errno;
#include <isc/condition.h>
#include <isc/commandline.h>
#include <isc/timer.h>
#include <isc/buffer.h>
#include <dns/message.h>
#include <dns/rdata.h>
@@ -74,7 +75,7 @@ isc_boolean_t busy = ISC_FALSE, in_use = ISC_FALSE;
char defclass[MXRD] = "IN";
char deftype[MXRD] = "A";
static char *rcodetext[] = {
static const char *rcodetext[] = {
"NOERROR",
"FORMERR",
"SERVFAIL",
@@ -94,7 +95,7 @@ static char *rcodetext[] = {
"BADVERS"
};
static char *rtypetext[] = {
static const char *rtypetext[] = {
"rtype_0 = ", /* 0 */
"internet address = ", /* 1 */
"nameserver = ", /* 2 */
@@ -250,7 +251,7 @@ printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
b);
check_result(result,
"dns_rdata_totext");
isc_buffer_used(b)[0]=0;
((char *)isc_buffer_used(b))[0]=0;
ptr = strtok(isc_buffer_base(b),
" \t\r\n");
if (ptr == NULL)
@@ -406,7 +407,7 @@ detailsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
b);
check_result(result,
"dns_rdata_totext");
isc_buffer_used(b)[0]=0;
((char *)isc_buffer_used(b))[0]=0;
ptr = strtok(isc_buffer_base(b),
" \t\r\n");
if (ptr == NULL)