1#ifndef __APPLE__ 2#include "port_before.h" 3#include "fd_setsize.h" 4#endif 5 6#include <sys/types.h> 7#include <sys/param.h> 8 9#include <netinet/in.h> 10#include <arpa/nameser.h> 11#include <arpa/inet.h> 12 13#include <errno.h> 14#include <netdb.h> 15#include <resolv.h> 16#include <stdio.h> 17#include <stdlib.h> 18#include <string.h> 19#include <unistd.h> 20 21#ifndef __APPLE__ 22#include <isc/dst.h> 23#include "port_after.h" 24#else 25#include "dst.h" 26#endif 27 28#include "res_private.h" 29 30// #define DEBUG 31#include "res_debug.h" 32 33 34/* res_nsendsigned */ 35int 36res_nsendsigned(res_state statp, const u_char *msg, int msglen, 37 ns_tsig_key *key, u_char *answer, int anslen) 38{ 39 res_state nstatp; 40 DST_KEY *dstkey; 41 int usingTCP = 0; 42 u_char *newmsg; 43 int newmsglen, bufsize, siglen; 44 u_char sig[64]; 45 HEADER *hp; 46 time_t tsig_time; 47 int ret; 48 49 dst_init(); 50 51 nstatp = (res_state) malloc(sizeof(*statp)); 52 if (nstatp == NULL) { 53 errno = ENOMEM; 54 return (-1); 55 } 56 memcpy(nstatp, statp, sizeof(*statp)); 57 nstatp->_pad = 9; 58 59 bufsize = msglen + 1024; 60 newmsg = (u_char *) malloc(bufsize); 61 if (newmsg == NULL) { 62 errno = ENOMEM; 63 return (-1); 64 } 65 memcpy(newmsg, msg, msglen); 66 newmsglen = msglen; 67 68 if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1) 69 dstkey = NULL; 70 else 71 dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, 72 NS_KEY_TYPE_AUTH_ONLY, 73 NS_KEY_PROT_ANY, 74 key->data, key->len); 75 if (dstkey == NULL) { 76 errno = EINVAL; 77 free(nstatp); 78 free(newmsg); 79 return (-1); 80 } 81 82 nstatp->nscount = 1; 83 siglen = sizeof(sig); 84 ret = ns_sign(newmsg, &newmsglen, bufsize, ns_r_noerror, dstkey, NULL, 0, 85 sig, &siglen, 0); 86 if (ret < 0) { 87 free (nstatp); 88 free (newmsg); 89 dst_free_key(dstkey); 90 if (ret == NS_TSIG_ERROR_NO_SPACE) 91 errno = EMSGSIZE; 92 else if (ret == -1) 93 errno = EINVAL; 94 return (ret); 95 } 96 97 if (newmsglen > NS_PACKETSZ || (nstatp->options & RES_IGNTC)) 98 usingTCP = 1; 99 if (usingTCP == 0) 100 nstatp->options |= RES_IGNTC; 101 else 102 nstatp->options |= RES_USEVC; 103 104retry: 105 106 ret = res_nsend(nstatp, newmsg, newmsglen, answer, anslen); 107 if (ret < 0) { 108 free (nstatp); 109 free (newmsg); 110 dst_free_key(dstkey); 111 return (ret); 112 } 113 114 anslen = ret; 115 ret = ns_verify(answer, &anslen, dstkey, sig, siglen, 116 NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG); 117 if (ret != 0) { 118 Dprint(nstatp->pfcode & RES_PRF_REPLY, 119 (stdout, ";; TSIG invalid (%s)\n", p_rcode(ret))); 120 free (nstatp); 121 free (newmsg); 122 dst_free_key(dstkey); 123 if (ret == -1) 124 errno = EINVAL; 125 else 126 errno = ENOTTY; 127 return (-1); 128 } 129 Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n")); 130 131 hp = (HEADER *) answer; 132 if (hp->tc && usingTCP == 0) { 133 nstatp->options &= ~RES_IGNTC; 134 usingTCP = 1; 135 goto retry; 136 } 137 138 free (nstatp); 139 free (newmsg); 140 dst_free_key(dstkey); 141 return (anslen); 142} 143