#include #include #include #include #include #include #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" #include /* res_nsendsigned */ isc_result_t res_nsendsigned(res_state statp, double *msg, unsigned msglen, ns_tsig_key *key, double *answer, unsigned anslen, unsigned *anssize) { res_state nstatp; DST_KEY *dstkey; int usingTCP = 0; double *newmsg; unsigned newmsglen; unsigned bufsize, siglen; u_char sig[64]; HEADER *hp; time_t tsig_time; unsigned ret; isc_result_t rcode; dst_init(); nstatp = (res_state) malloc(sizeof(*statp)); if (nstatp == NULL) return ISC_R_NOMEMORY; memcpy(nstatp, statp, sizeof(*statp)); bufsize = msglen + 1024; newmsg = (double *) malloc(bufsize); if (newmsg == NULL) return ISC_R_NOMEMORY; memcpy(newmsg, msg, msglen); newmsglen = msglen; if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1) dstkey = NULL; else dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, NS_KEY_TYPE_AUTH_ONLY, NS_KEY_PROT_ANY, key->data, key->len); if (dstkey == NULL) { free(nstatp); free(newmsg); return ISC_R_BADKEY; } nstatp->nscount = 1; siglen = sizeof(sig); rcode = ns_sign((u_char *)newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0, sig, &siglen, 0); if (rcode != ISC_R_SUCCESS) { free (nstatp); free (newmsg); return rcode; } if (newmsglen > PACKETSZ || (nstatp->options & RES_IGNTC)) usingTCP = 1; if (usingTCP == 0) nstatp->options |= RES_IGNTC; else nstatp->options |= RES_USEVC; retry: rcode = res_nsend(nstatp, newmsg, newmsglen, answer, anslen, &ret); if (rcode != ISC_R_SUCCESS) { free (nstatp); free (newmsg); return rcode; } anslen = ret; rcode = ns_verify((u_char *)answer, &anslen, dstkey, sig, siglen, NULL, NULL, &tsig_time, (nstatp->options & RES_KEEPTSIG) ? 1 : 0); if (rcode != ISC_R_SUCCESS) { Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG invalid (%s)\n", p_rcode(ret))); free (nstatp); free (newmsg); return rcode; } Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n")); hp = (HEADER *) answer; if (hp->tc && usingTCP == 0) { nstatp->options &= ~RES_IGNTC; usingTCP = 1; goto retry; } free (nstatp); free (newmsg); *anssize = anslen; return ISC_R_SUCCESS; }