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