git ssb

15+

ansuz / dnssb



Commit 7216c5147c617ec965b6bf02ee91da180a9d4cb7

Handle AXFR queries

cel committed on 11/26/2016, 6:09:27 PM
Parent: c77b37a319fc698a43cdde6568d83d251a31753b

Files changed

lib/query.jschanged
lib/server.jschanged
lib/query.jsView
@@ -98,16 +98,29 @@
9898 Pull.filter());
9999 };
100100
101101 function expandName(name, wildcard) {
102- var names = {};
102 + var names = {'': true};
103 + names[name] = true;
103104 for (var labels = name.split(/\./); labels.length; labels.shift()) {
104105 if (wildcard) labels[0] = wildcard;
105106 names[labels.join('.')] = true;
106107 }
107108 return names;
108109 }
109110
111 +function Records() {
112 + this.recs = [];
113 +}
114 +
115 +Records.prototype.addRecord = function (record) {
116 + this.recs.push(record);
117 +};
118 +
119 +Records.prototype.getRecords = function () {
120 + return this.recs;
121 +};
122 +
110123 function Wildcards() {
111124 this.lengths = [];
112125 this.recordsByLength = {};
113126 }
@@ -134,10 +147,10 @@
134147 function ZoneSerials() {
135148 this.serials = {};
136149 }
137150
138-ZoneSerials.prototype.addRecord = function (record) {
139- for (var zone in expandName(record.name)) {
151 +ZoneSerials.prototype.addRecord = function (zones) {
152 + for (var zone in zones) {
140153 this.serials[zone] = (+this.serials[zone] || 0) + 1;
141154 }
142155 };
143156
@@ -178,12 +191,15 @@
178191 }
179192
180193 // recursive query
181194 Query.queryRecursive = function (sbot, question, stack, cb) {
195 + var isTransfer = question.type === 'AXFR'
196 +
182197 var result = {
183198 answers: [],
184199 authorities: [],
185200 additionals: [],
201 + questions: [],
186202 expires: Date.now() + 60*60e3,
187203 };
188204
189205 // avoid infinite recursion
@@ -201,12 +217,13 @@
201217
202218 merge(result.additionals, res.additionals);
203219 merge(result.answers, res.answers);
204220 merge(result.authorities, res.authorities);
221 + merge(result.questions, res.questions);
205222 if (res.expires < result.expires) result.expires = res.expires;
206223
207224 // recurse on CNAMEs
208- if (question.type !== 'CNAME') {
225 + if (!isTransfer && question.type !== 'CNAME') {
209226 var stack2 = stack.concat(question)
210227 res.answers.filter(function (answer) {
211228 return answer.type === 'CNAME';
212229 }).map(function (record) {
@@ -229,37 +246,46 @@
229246 // look up records that match a question, including wildcard records
230247 // and zone authority records
231248 var authorityDomains = expandName(question.name);
232249 var wildcardDomains = expandName(question.name, '*');
250 + var isTransfer = question.type === 'AXFR'
233251 var authorities = new Wildcards();
234- var answers = new Wildcards();
252 + var answers = isTransfer ? new Records() : new Wildcards();
235253 var zoneSerials = new ZoneSerials();
236254 var result = {};
237255 Pull(Query.all(sbot),
238256 Pull.filter(function (record) {
239- zoneSerials.addRecord(record);
240- var nameMatches = record.name == question.name
241- || record.name in wildcardDomains
257 + var recordDomains = expandName(record.name);
258 + zoneSerials.addRecord(recordDomains);
259 + var nameMatches = isTransfer
260 + ? question.name in recordDomains
261 + : record.name in wildcardDomains;
242262 if (nameMatches) {
243263 result.domainExists = true;
244264 }
245265 if (record.type === 'SOA') {
246- return record.name in authorityDomains
266 + return record.name in authorityDomains;
247267 }
248268 return nameMatches
249- && (record.type == question.type || record.type === 'CNAME')
250- && record.class == question.class;
269 + && (isTransfer
270 + || question.type === record.type
271 + || question.type === '*'
272 + || 'CNAME' === record.type)
273 + && (question.class === record.class
274 + || question.class === '*');
251275 }),
252276 Query.drainSet(function (record) {
253277 if (record.type === 'SOA') {
254278 result.authoritative = true;
255- if (question.type === 'SOA'
256- && question.class === record.class
257- && (question.name === record.name
258- || record.name in wildcardDomains)) {
279 + if (question.class === record.class
280 + && question.type === 'SOA'
281 + && record.name in wildcardDomains) {
259282 answers.addRecord(record);
260283 } else {
261284 authorities.addRecord(record);
285 + if (isTransfer) {
286 + answers.addRecord(record);
287 + }
262288 }
263289 } else {
264290 answers.addRecord(record);
265291 }
@@ -282,7 +308,18 @@
282308 }
283309 });
284310 result.expires = Date.now() + ttl * 60e3;
285311 result.additionals = [];
312 + result.questions = [];
313 +
314 + if (isTransfer) {
315 + // RFC 5936, Section 2.2
316 + result.questions.push(question);
317 + // pick a SOA record to use as the bookend
318 + var soa = result.authorities.splice(0)[0];
319 + result.answers = [soa].concat(result.answers.filter(function (r) {
320 + return r !== soa;
321 + }), [soa]);
322 + }
286323 cb(null, result);
287324 }));
288325 };
lib/server.jsView
@@ -63,8 +63,9 @@
6363 var auths = authorities.map(Format.recordToLine).join(", ")
6464 console.log("%s: %s%s", q.name, recs,
6565 auths ? '. auths: ' : '', auths);
6666 }
67 + res.question = result.questions;
6768 res.answer = result.answers;
6869 res.authority = result.authorities;
6970 res.additional = result.additionals;
7071 res.end();

Built with git-ssb-web