]> git.saurik.com Git - apple/libresolv.git/blob - res_sendsigned.c
libresolv-54.tar.gz
[apple/libresolv.git] / res_sendsigned.c
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 */
35 int
36 res_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
104 retry:
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 }