djbdnscurve6 45
djbdnscurve6
Loading...
Searching...
No Matches
axfrdns.c
Go to the documentation of this file.
1#include <unistd.h>
2#include "droproot.h"
3#include "exit.h"
4#include "env.h"
5#include "uint_t.h"
6#include "ip.h"
7#include "tai.h"
8#include "buffer.h"
9#include "timeout.h"
10#include "open.h"
11#include "seek.h"
12#include "cdbread.h"
13#include "stralloc.h"
14#include "logmsg.h"
15#include "str.h"
16#include "byte.h"
17#include "case.h"
18#include "dns.h"
19#include "scan.h"
20#include "qlog.h"
21#include "response.h"
22#include "clientloc.h"
23
24extern int respond(char *,char *,char *);
25
26#define WHO "axfrdns"
27
28void nomem()
29{
30 logmsg(WHO,111,FATAL,"out of memory");
31}
33{
34 logmsg(WHO,111,FATAL,"truncated request");
35}
37{
38 logmsg(WHO,111,FATAL,"unable to write to network");
39}
41{
42 logmsg(WHO,111,FATAL,"unable to read from network");
43}
45{
46 logmsg(WHO,111,FATAL,"unable to locate information in data.cdb");
47}
49{
50 logmsg(WHO,111,FATAL,"unable to read data.cdb");
51}
53{
54 logmsg(WHO,111,FATAL,B("unable to read data.cdb: ","format error"));
55}
56
57ssize_t safewrite(int fd,char *buf,unsigned int len)
58{
59 int r;
60
61 r = timeoutwrite(60,fd,buf,len);
62 if (r <= 0) die_netwrite();
63 return r;
64}
65
66char netwritespace[1024];
67buffer netwrite = BUFFER_INIT(safewrite,1,netwritespace,sizeof(netwritespace));
68
69void print(char *buf,unsigned int len)
70{
71 char tcpheader[2];
72 uint16_pack_big(tcpheader,len);
73 buffer_put(&netwrite,tcpheader,2);
74 buffer_put(&netwrite,buf,len);
75 buffer_flush(&netwrite);
76}
77
78char *axfr;
79static char *axfrok;
80
81void axfrcheck(char *q)
82{
83 int i;
84 int j;
85
86 if (!axfr) return;
87
88 i = j = 0;
89 for (;;) {
90 if (!axfr[i] || (axfr[i] == '/')) {
91 if (i > j) {
92 if (dns_domain_fromdot(&axfrok,axfr + j,i - j) <= 0) nomem();
93 if (dns_domain_equal(q,axfrok)) return;
94 }
95 j = i + 1;
96 }
97 if (!axfr[i]) break;
98 ++i;
99 }
100
101 logmsg(WHO,111,FATAL,"disallowed zone transfer request");
102}
103
104static char *zone;
105unsigned int zonelen;
106char typeclass[4];
107
109buffer bcdb;
110char bcdbspace[1024];
111
112void get_cdb(char *buf,unsigned int len)
113{
114 int r;
115
116 while (len > 0) {
117 r = buffer_get(&bcdb,buf,len);
118 if (r < 0) die_cdbread();
119 if (!r) die_cdbformat();
120 buf += r;
121 len -= r;
122 }
123}
124
125char ip[16];
126unsigned long port;
127char clientloc[2];
128
129struct tai now;
130char data[32767];
131uint32 dlen;
132uint32 dpos;
133
134void dns_copy(char *buf,unsigned int len)
135{
137 if (!dpos) die_cdbread();
138}
139
140void doname(stralloc *sa)
141{
142 static char *d;
144 if (!dpos) die_cdbread();
145 if (!stralloc_catb(sa,d,dns_domain_length(d))) nomem();
146}
147
148int build(stralloc *sa,char *q,int flagsoa,char id[2])
149{
150 unsigned int rdatapos;
151 char misc[20];
152 char type[2];
153 char recordloc[2];
154 char ttl[4];
155 char ttd[8];
156 struct tai cutoff;
157
158 dpos = 0;
159 dns_copy(type,2);
160 if (flagsoa) if (byte_diff(type,2,DNS_T_SOA)) return 0;
161 if (!flagsoa) if (byte_equal(type,2,DNS_T_SOA)) return 0;
162
163/*
164 Byte \204 (meaning: response, opcode 0, authoritative, not truncated, recursion not desired), or, optionally,
165 QR OPCODE AA TC RD
166 \205 if the client used byte \001. named-xfer rejects responses that do not have at least bits \204.
167 Byte \000 (meaning: recursion not available, no Z bits, RCODE 0), or, optionally, \200.
168 RA Z+AD+CD RCODE
169 Bytes \000\000 (meaning no questions), or \000\001 (meaning one question).
170 QDCOUNT=0 QDCOUNT=1
1712 bytes, nly \000\001, indicating the number of answer records below.
172 ANCOUNT
173 Bytes \000\000 (meaning no authority records).
174 NSCOUNT
175 Bytes \000\000 (meaning no additional records).
176 ARCOUNT
177 NOTE: \000 = \00 = \0
178*/
179
180 if (!stralloc_copyb(sa,id,2)) nomem(); // ID
181 if (!stralloc_catb(sa,"\204\000\0\0\0\1\0\0\0\0",10)) nomem(); // following header
182
183 dns_copy(misc,1);
184 if ((misc[0] == '=' + 1) || (misc[0] == '*' + 1)) { // '*'+1 = 43 ; '='+1 = 62 ; bug fix?
185 --misc[0];
186 dns_copy(recordloc,2);
187 if (byte_diff(recordloc,2,clientloc)) return 0;
188 }
189 if (misc[0] == '*') {
190 if (flagsoa) return 0;
191 if (!stralloc_catb(sa,"\1*",2)) nomem();
192 }
193 if (!stralloc_catb(sa,q,dns_domain_length(q))) nomem();
194 if (!stralloc_catb(sa,type,2)) nomem();
195
196 dns_copy(ttl,4);
197 dns_copy(ttd,8);
198 if (byte_diff(ttd,8,"\0\0\0\0\0\0\0\0")) {
199 tai_unpack(ttd,&cutoff);
200 if (byte_equal(ttl,4,"\0\0\0\0")) {
201 if (tai_less(&cutoff,&now)) return 0;
202 uint32_pack_big(ttl,2);
203 }
204 else
205 if (!tai_less(&cutoff,&now)) return 0;
206 }
207
208 if (!stralloc_catb(sa,DNS_C_IN,2)) nomem();
209 if (!stralloc_catb(sa,ttl,4)) nomem();
210 if (!stralloc_catb(sa,"\0\0",2)) nomem();
211 rdatapos = sa->len;
212
213 if (byte_equal(type,2,DNS_T_SOA)) {
214 doname(sa);
215 doname(sa);
216 dns_copy(misc,20);
217 if (!stralloc_catb(sa,misc,20)) nomem();
218 }
219 else if (byte_equal(type,2,DNS_T_NS) || byte_equal(type,2,DNS_T_PTR) || byte_equal(type,2,DNS_T_CNAME)) {
220 doname(sa);
221 }
222 else if (byte_equal(type,2,DNS_T_MX)) {
223 dns_copy(misc,2);
224 if (!stralloc_catb(sa,misc,2)) nomem();
225 doname(sa);
226 }
227 else
228 if (!stralloc_catb(sa,data + dpos,dlen - dpos)) nomem();
229
230 if (sa->len > 65535) die_cdbformat();
231 uint16_pack_big(sa->s + rdatapos - 2,sa->len - rdatapos);
232 return 1;
233}
234
235static struct cdb c;
236static char *q;
237static stralloc soa;
238static stralloc message;
239
240void doaxfr(char id[2])
241{
242 char key[MSGSIZE];
243 uint32 klen;
244 char num[4];
245 uint32 eod;
246 uint32 pos;
247 int r;
248
249 axfrcheck(zone);
250
252
253 tai_now(&now);
254 cdb_init(&c,fdcdb);
255
256 cdb_findstart(&c);
257 for (;;) {
258 r = cdb_findnext(&c,zone,zonelen);
259 if (r == -1) die_cdbread();
260 if (!r) die_outside();
261 dlen = cdb_datalen(&c);
262 if (dlen > sizeof(data)) die_cdbformat();
263 if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) die_cdbformat();
264 if (build(&soa,zone,1,id)) break;
265 }
266
267 cdb_free(&c);
268 print(soa.s,soa.len);
269
270 seek_begin(fdcdb);
271 buffer_init(&bcdb,buffer_unixread,fdcdb,bcdbspace,sizeof(bcdbspace));
272
273 pos = 0;
274 get_cdb(num,4); pos += 4;
275 uint32_unpack(num,&eod);
276 while (pos < 2048) { get_cdb(num,4); pos += 4; }
277
278 while (pos < eod) {
279 if (eod - pos < 8) die_cdbformat();
280 get_cdb(num,4); pos += 4;
281 uint32_unpack(num,&klen);
282 get_cdb(num,4); pos += 4;
283 uint32_unpack(num,&dlen);
284 if (eod - pos < klen) die_cdbformat();
285 pos += klen;
286 if (eod - pos < dlen) die_cdbformat();
287 pos += dlen;
288
289 if (klen > sizeof(key)) die_cdbformat();
290 get_cdb(key,klen);
291 if (dlen > sizeof(data)) die_cdbformat();
293
294 if ((klen > 1) && (key[0] == 0)) continue; /* location */
295 if (klen < 1) die_cdbformat();
296 if (dns_packet_getname(key,klen,0,&q) != klen) die_cdbformat();
297 if (!dns_domain_suffix(q,zone)) continue;
298 if (!build(&message,q,0,id)) continue;
299 print(message.s,message.len);
300 }
301
302 print(soa.s,soa.len);
303}
304
305void netread(char *buf,unsigned int len)
306{
307 int r;
308
309 while (len > 0) {
310 r = timeoutread(60,0,buf,len);
311 if (r == 0) _exit(0);
312 if (r < 0) die_netread();
313 buf += r; len -= r;
314 }
315}
316
317char tcpheader[2];
319uint16 len;
320
321static char seed[128];
322
323int main()
324{
325 unsigned int pos;
326 char header[12];
327 char qtype[2];
328 char qclass[2];
329 const char *x;
330
331 droproot(WHO);
332 dns_random_init(seed);
333
334 axfr = env_get("AXFR");
335
336 x = env_get("TCP6REMOTEIP");
337 if (!x) x = env_get("TCPREMOTEIP");
338 if (x && ip6_scan(x,ip))
339 ;
340 else
341 byte_zero(ip,16);
342
343 x = env_get("TCP6REMOTEPORT");
344 if (!x)
345 x = env_get("TCPREMOTEPORT");
346 if (!x) x = "0";
347 scan_ulong(x,&port);
348
349 for (;;) {
351 uint16_unpack_big(tcpheader,&len);
352 if (len > MSGSIZE) logmsg(WHO,111,FATAL,"excessively large request");
353 netread(buf,len);
354
355 pos = dns_packet_copy(buf,len,0,header,12); if (!pos) die_truncated();
356 if (header[2] & 254) logmsg(WHO,111,FATAL,"bogus query");
357 if (header[4] || (header[5] != 1)) logmsg(WHO,111,FATAL,"bogus query");
358
359 pos = dns_packet_getname(buf,len,pos,&zone); if (!pos) die_truncated();
361 pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) die_truncated();
362 pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) die_truncated();
363
364 if (byte_diff(qclass,2,DNS_C_IN) && byte_diff(qclass,2,DNS_C_ANY))
365 logmsg(WHO,111,FATAL,"bogus query: bad class");
366
367 qlog(ip,port,header,zone,qtype," ");
368
369 if (byte_equal(qtype,2,DNS_T_AXFR)) {
370 case_lowerb(zone,zonelen);
371 fdcdb = open_read("data.cdb");
372 if (fdcdb == -1) die_cdbread();
373 doaxfr(header);
374 close(fdcdb);
375 }
376 else {
377 if (!response_query(zone,qtype,qclass)) nomem();
378 response[2] |= 4;
379 case_lowerb(zone,zonelen);
380 response_id(header);
381 response[3] &= ~128;
382 if (!(header[2] & 1)) response[2] &= ~1;
383 if (!respond(zone,qtype,ip)) die_outside();
385 }
386 }
387}
int fd
Definition: axfr-get.c:103
buffer netread
Definition: axfr-get.c:89
char data[32767]
Definition: axfrdns.c:130
void die_cdbread()
Definition: axfrdns.c:48
void dns_copy(char *buf, unsigned int len)
Definition: axfrdns.c:134
void die_truncated()
Definition: axfrdns.c:32
int fdcdb
Definition: axfrdns.c:108
buffer bcdb
Definition: axfrdns.c:109
unsigned long port
Definition: axfrdns.c:126
void die_cdbformat()
Definition: axfrdns.c:52
char netwritespace[1024]
Definition: axfrdns.c:66
void die_outside()
Definition: axfrdns.c:44
int respond(char *, char *, char *)
void get_cdb(char *buf, unsigned int len)
Definition: axfrdns.c:112
char bcdbspace[1024]
Definition: axfrdns.c:110
void die_netread()
Definition: axfrdns.c:40
unsigned int zonelen
Definition: axfrdns.c:105
void nomem()
Definition: axfrdns.c:28
ssize_t safewrite(int fd, char *buf, unsigned int len)
Definition: axfrdns.c:57
struct tai now
Definition: axfrdns.c:129
int build(stralloc *sa, char *q, int flagsoa, char id[2])
Definition: axfrdns.c:148
void die_netwrite()
Definition: axfrdns.c:36
char clientloc[2]
Definition: axfrdns.c:127
void axfrcheck(char *q)
Definition: axfrdns.c:81
char ip[16]
Definition: axfrdns.c:125
uint16 len
Definition: axfrdns.c:319
char typeclass[4]
Definition: axfrdns.c:106
void print(char *buf, unsigned int len)
Definition: axfrdns.c:69
char * axfr
Definition: axfrdns.c:78
char buf[MSGSIZE]
Definition: axfrdns.c:318
buffer netwrite
Definition: axfrdns.c:67
#define WHO
Definition: axfrdns.c:26
uint32 dpos
Definition: axfrdns.c:132
int main()
Definition: axfrdns.c:323
void doname(stralloc *sa)
Definition: axfrdns.c:140
void doaxfr(char id[2])
Definition: axfrdns.c:240
uint32 dlen
Definition: axfrdns.c:131
char tcpheader[2]
Definition: axfrdns.c:317
int find_clientloc(char clientloc[2], const char ip[16])
Definition: clientloc.c:8
#define DNS_T_AXFR
Definition: dns.h:84
#define DNS_C_IN
Definition: dns.h:53
#define MSGSIZE
Definition: dns.h:38
#define DNS_T_PTR
Definition: dns.h:60
#define DNS_T_SOA
Definition: dns.h:59
#define DNS_T_NS
Definition: dns.h:57
#define DNS_T_CNAME
Definition: dns.h:58
#define DNS_C_ANY
Definition: dns.h:54
#define DNS_T_MX
Definition: dns.h:62
int dns_domain_fromdot(char **out, const char *buf, unsigned int n)
Definition: dns_dfd.c:6
int dns_domain_equal(const char *dn1, const char *dn2)
Definition: dns_domain.c:39
unsigned int dns_domain_length(const char *dn)
Definition: dns_domain.c:6
int dns_domain_suffix(const char *big, const char *little)
Definition: dns_domain.c:50
unsigned int dns_packet_getname(const char *buf, unsigned int len, unsigned int pos, char **d)
Definition: dns_packet.c:35
unsigned int dns_packet_copy(const char *buf, unsigned int len, unsigned int pos, char *out, unsigned int outlen)
Definition: dns_packet.c:8
void dns_random_init(const char data[128])
Definition: dns_random.c:37
struct line * x
char type[2]
Definition: dnsq.c:56
void droproot(const char *fatal)
Definition: droproot.c:8
void d(const char *home, const char *subdir, int uid, int gid, int mode)
void qlog(const char *, uint16, const char *, const char *, const char *, const char *)
struct cdb_make cdb
Definition: rbldns-data.c:36
void response_id(const char *)
char response[]
Definition: response.c:6
unsigned int response_len
Definition: response.c:7
int response_query(const char *, const char *, const char *)