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