1/* 2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (c) 1995-2003 by Internet Software Consortium 4 * 5 * Permission to use, copy, modify, and 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 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * Internet Systems Consortium, Inc. 18 * 950 Charter Street 19 * Redwood City, CA 94063 20 * <info@isc.org> 21 * http://www.isc.org/ 22 */ 23 24#include <sys/types.h> 25#include <sys/param.h> 26 27#include <netinet/in.h> 28#include <arpa/inet.h> 29#include <sys/socket.h> 30 31#include <errno.h> 32#include <netdb.h> 33#include <stdio.h> 34#include <stdlib.h> 35#include <string.h> 36#include <unistd.h> 37 38#include "minires/minires.h" 39#include "arpa/nameser.h" 40 41#include <isc-dhcp/dst.h> 42 43/* res_nsendsigned */ 44isc_result_t 45res_nsendsigned(res_state statp, 46 double *msg, unsigned msglen, ns_tsig_key *key, 47 double *answer, unsigned anslen, unsigned *anssize) 48{ 49 res_state nstatp; 50 DST_KEY *dstkey; 51 int usingTCP = 0; 52 double *newmsg; 53 unsigned newmsglen; 54 unsigned bufsize, siglen; 55 u_char sig[64]; 56 HEADER *hp; 57 time_t tsig_time; 58 unsigned ret; 59 isc_result_t rcode; 60 61 dst_init(); 62 63 nstatp = (res_state) malloc(sizeof(*statp)); 64 if (nstatp == NULL) 65 return ISC_R_NOMEMORY; 66 memcpy(nstatp, statp, sizeof(*statp)); 67 68 bufsize = msglen + 1024; 69 newmsg = (double *) malloc(bufsize); 70 if (newmsg == NULL) 71 return ISC_R_NOMEMORY; 72 memcpy(newmsg, msg, msglen); 73 newmsglen = msglen; 74 75 if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1) 76 dstkey = NULL; 77 else 78 dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, 79 NS_KEY_TYPE_AUTH_ONLY, 80 NS_KEY_PROT_ANY, 81 key->data, key->len); 82 if (dstkey == NULL) { 83 free(nstatp); 84 free(newmsg); 85 return ISC_R_BADKEY; 86 } 87 88 nstatp->nscount = 1; 89 siglen = sizeof(sig); 90 rcode = ns_sign((u_char *)newmsg, &newmsglen, bufsize, 91 NOERROR, dstkey, NULL, 0, 92 sig, &siglen, 0); 93 if (rcode != ISC_R_SUCCESS) { 94 free (nstatp); 95 free (newmsg); 96 return rcode; 97 } 98 99 if (newmsglen > PACKETSZ || (nstatp->options & RES_IGNTC)) 100 usingTCP = 1; 101 if (usingTCP == 0) 102 nstatp->options |= RES_IGNTC; 103 else 104 nstatp->options |= RES_USEVC; 105 106retry: 107 108 rcode = res_nsend(nstatp, newmsg, newmsglen, answer, anslen, &ret); 109 if (rcode != ISC_R_SUCCESS) { 110 free (nstatp); 111 free (newmsg); 112 return rcode; 113 } 114 115 anslen = ret; 116 rcode = ns_verify((u_char *)answer, &anslen, dstkey, sig, siglen, 117 NULL, NULL, &tsig_time, 118 (nstatp->options & RES_KEEPTSIG) ? 1 : 0); 119 if (rcode != ISC_R_SUCCESS) { 120 Dprint(nstatp->pfcode & RES_PRF_REPLY, 121 (stdout, ";; TSIG invalid (%s)\n", p_rcode(ret))); 122 free (nstatp); 123 free (newmsg); 124 return rcode; 125 } 126 Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n")); 127 128 hp = (HEADER *) answer; 129 if (hp->tc && usingTCP == 0) { 130 nstatp->options &= ~RES_IGNTC; 131 usingTCP = 1; 132 goto retry; 133 } 134 135 free (nstatp); 136 free (newmsg); 137 *anssize = anslen; 138 return ISC_R_SUCCESS; 139} 140