1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include <sys/types.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "minires/minires.h"
#include "arpa/nameser.h"
#include <isc-dhcp/dst.h>
/* res_nsendsigned */
isc_result_t
res_nsendsigned(res_state statp,
double *msg, unsigned msglen, ns_tsig_key *key,
double *answer, unsigned anslen, unsigned *anssize)
{
res_state nstatp;
DST_KEY *dstkey;
int usingTCP = 0;
double *newmsg;
unsigned newmsglen;
unsigned bufsize, siglen;
u_char sig[64];
HEADER *hp;
time_t tsig_time;
unsigned ret;
isc_result_t rcode;
dst_init();
nstatp = (res_state) malloc(sizeof(*statp));
if (nstatp == NULL)
return ISC_R_NOMEMORY;
memcpy(nstatp, statp, sizeof(*statp));
bufsize = msglen + 1024;
newmsg = (double *) malloc(bufsize);
if (newmsg == NULL)
return ISC_R_NOMEMORY;
memcpy(newmsg, msg, msglen);
newmsglen = msglen;
if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1)
dstkey = NULL;
else
dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5,
NS_KEY_TYPE_AUTH_ONLY,
NS_KEY_PROT_ANY,
key->data, key->len);
if (dstkey == NULL) {
free(nstatp);
free(newmsg);
return ISC_R_BADKEY;
}
nstatp->nscount = 1;
siglen = sizeof(sig);
rcode = ns_sign((u_char *)newmsg, &newmsglen, bufsize,
NOERROR, dstkey, NULL, 0,
sig, &siglen, 0);
if (rcode != ISC_R_SUCCESS) {
free (nstatp);
free (newmsg);
return rcode;
}
if (newmsglen > PACKETSZ || (nstatp->options & RES_IGNTC))
usingTCP = 1;
if (usingTCP == 0)
nstatp->options |= RES_IGNTC;
else
nstatp->options |= RES_USEVC;
retry:
rcode = res_nsend(nstatp, newmsg, newmsglen, answer, anslen, &ret);
if (rcode != ISC_R_SUCCESS) {
free (nstatp);
free (newmsg);
return rcode;
}
anslen = ret;
rcode = ns_verify((u_char *)answer, &anslen, dstkey, sig, siglen,
NULL, NULL, &tsig_time,
(nstatp->options & RES_KEEPTSIG) ? 1 : 0);
if (rcode != ISC_R_SUCCESS) {
Dprint(nstatp->pfcode & RES_PRF_REPLY,
(stdout, ";; TSIG invalid (%s)\n", p_rcode(ret)));
free (nstatp);
free (newmsg);
return rcode;
}
Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n"));
hp = (HEADER *) answer;
if (hp->tc && usingTCP == 0) {
nstatp->options &= ~RES_IGNTC;
usingTCP = 1;
goto retry;
}
free (nstatp);
free (newmsg);
*anssize = anslen;
return ISC_R_SUCCESS;
}
|