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
res_nsendsigned(res_state statp,const u_char * msg,int msglen,ns_tsig_key * key,u_char * answer,int anslen)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