1 #include "port_before.h" 2 #include "fd_setsize.h" 3 4 #include <sys/types.h> 5 #include <sys/param.h> 6 7 #include <netinet/in.h> 8 #include <arpa/nameser.h> 9 #include <arpa/inet.h> 10 11 #include <isc/dst.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 #include "port_after.h" 22 23 #define DEBUG 24 #include "res_debug.h" 25 26 27 /*% res_nsendsigned */ 28 int 29 res_nsendsigned(res_state statp, const u_char *msg, int msglen, 30 ns_tsig_key *key, u_char *answer, int anslen) 31 { 32 res_state nstatp; 33 DST_KEY *dstkey; 34 int usingTCP = 0; 35 u_char *newmsg; 36 int newmsglen, bufsize, siglen; 37 u_char sig[64]; 38 HEADER *hp; 39 time_t tsig_time; 40 int ret; 41 int len; 42 43 dst_init(); 44 45 nstatp = (res_state) malloc(sizeof(*statp)); 46 if (nstatp == NULL) { 47 errno = ENOMEM; 48 return (-1); 49 } 50 memcpy(nstatp, statp, sizeof(*statp)); 51 52 bufsize = msglen + 1024; 53 newmsg = (u_char *) malloc(bufsize); 54 if (newmsg == NULL) { 55 free(nstatp); 56 errno = ENOMEM; 57 return (-1); 58 } 59 memcpy(newmsg, msg, msglen); 60 newmsglen = msglen; 61 62 if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1) 63 dstkey = NULL; 64 else 65 dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, 66 NS_KEY_TYPE_AUTH_ONLY, 67 NS_KEY_PROT_ANY, 68 key->data, key->len); 69 if (dstkey == NULL) { 70 errno = EINVAL; 71 free(nstatp); 72 free(newmsg); 73 return (-1); 74 } 75 76 nstatp->nscount = 1; 77 siglen = sizeof(sig); 78 ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0, 79 sig, &siglen, 0); 80 if (ret < 0) { 81 free (nstatp); 82 free (newmsg); 83 dst_free_key(dstkey); 84 if (ret == NS_TSIG_ERROR_NO_SPACE) 85 errno = EMSGSIZE; 86 else if (ret == -1) 87 errno = EINVAL; 88 return (ret); 89 } 90 91 if (newmsglen > PACKETSZ || nstatp->options & RES_USEVC) 92 usingTCP = 1; 93 if (usingTCP == 0) 94 nstatp->options |= RES_IGNTC; 95 else 96 nstatp->options |= RES_USEVC; 97 /* 98 * Stop res_send printing the answer. 99 */ 100 nstatp->options &= ~RES_DEBUG; 101 nstatp->pfcode &= ~RES_PRF_REPLY; 102 103 retry: 104 105 len = res_nsend(nstatp, newmsg, newmsglen, answer, anslen); 106 if (len < 0) { 107 free (nstatp); 108 free (newmsg); 109 dst_free_key(dstkey); 110 return (len); 111 } 112 113 ret = ns_verify(answer, &len, dstkey, sig, siglen, 114 NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG); 115 if (ret != 0) { 116 Dprint((statp->options & RES_DEBUG) || 117 ((statp->pfcode & RES_PRF_REPLY) && 118 (statp->pfcode & RES_PRF_HEAD1)), 119 (stdout, ";; got answer:\n")); 120 121 DprintQ((statp->options & RES_DEBUG) || 122 (statp->pfcode & RES_PRF_REPLY), 123 (stdout, "%s", ""), 124 answer, (anslen > len) ? len : anslen); 125 126 if (ret > 0) { 127 Dprint(statp->pfcode & RES_PRF_REPLY, 128 (stdout, ";; server rejected TSIG (%s)\n", 129 p_rcode(ret))); 130 } else { 131 Dprint(statp->pfcode & RES_PRF_REPLY, 132 (stdout, ";; TSIG invalid (%s)\n", 133 p_rcode(-ret))); 134 } 135 136 free (nstatp); 137 free (newmsg); 138 dst_free_key(dstkey); 139 if (ret == -1) 140 errno = EINVAL; 141 else 142 errno = ENOTTY; 143 return (-1); 144 } 145 146 hp = (HEADER *) answer; 147 if (hp->tc && !usingTCP && (statp->options & RES_IGNTC) == 0U) { 148 nstatp->options &= ~RES_IGNTC; 149 usingTCP = 1; 150 goto retry; 151 } 152 Dprint((statp->options & RES_DEBUG) || 153 ((statp->pfcode & RES_PRF_REPLY) && 154 (statp->pfcode & RES_PRF_HEAD1)), 155 (stdout, ";; got answer:\n")); 156 157 DprintQ((statp->options & RES_DEBUG) || 158 (statp->pfcode & RES_PRF_REPLY), 159 (stdout, "%s", ""), 160 answer, (anslen > len) ? len : anslen); 161 162 Dprint(statp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n")); 163 164 free (nstatp); 165 free (newmsg); 166 dst_free_key(dstkey); 167 return (len); 168 } 169 170 /*! \file */ 171