WIP Building out all features necessary for Let's Encrypt #6

Closed
coolaj86 wants to merge 17 commits from more-acme into master
1 changed files with 52 additions and 52 deletions
Showing only changes of commit c974cb7039 - Show all commits

104
server.js
View File

@ -16,10 +16,10 @@ app.use('/api', express.json());
app.get('/api/dns/:domain', function (req, res, next) { app.get('/api/dns/:domain', function (req, res, next) {
var domain = req.params.domain; var domain = req.params.domain;
var casedDomain = domain.toLowerCase().split('').map(function (ch) { var casedDomain = domain.toLowerCase().split('').map(function (ch) {
// dns0x20 takes advantage of the fact that the binary operation for toUpperCase is // dns0x20 takes advantage of the fact that the binary operation for toUpperCase is
// ch = ch | 0x20; // ch = ch | 0x20;
return Math.round(Math.random()) % 2 ? ch : ch.toUpperCase(); return Math.round(Math.random()) % 2 ? ch : ch.toUpperCase();
}).join(''); }).join('');
var typ = req.query.type; var typ = req.query.type;
var query = { var query = {
header: { header: {
@ -40,60 +40,60 @@ app.get('/api/dns/:domain', function (req, res, next) {
} }
] ]
}; };
var opts = { var opts = {
onError: function (err) { onError: function (err) {
next(err); next(err);
} }
, onMessage: function (packet) { , onMessage: function (packet) {
var fail0x20; var fail0x20;
if (packet.id !== query.id) { if (packet.id !== query.id) {
console.error('[SECURITY] ignoring packet for \'' + packet.question[0].name + '\' due to mismatched id'); console.error('[SECURITY] ignoring packet for \'' + packet.question[0].name + '\' due to mismatched id');
console.error(packet); console.error(packet);
return; return;
} }
packet.question.forEach(function (q) { packet.question.forEach(function (q) {
// if (-1 === q.name.lastIndexOf(cli.casedQuery)) // if (-1 === q.name.lastIndexOf(cli.casedQuery))
if (q.name !== casedDomain) { if (q.name !== casedDomain) {
fail0x20 = q.name; fail0x20 = q.name;
} }
}); });
[ 'question', 'answer', 'authority', 'additional' ].forEach(function (group) { [ 'question', 'answer', 'authority', 'additional' ].forEach(function (group) {
(packet[group]||[]).forEach(function (a) { (packet[group]||[]).forEach(function (a) {
var an = a.name; var an = a.name;
var i = domain.toLowerCase().lastIndexOf(a.name.toLowerCase()); // answer is something like ExAMPle.cOM and query was wWw.ExAMPle.cOM var i = domain.toLowerCase().lastIndexOf(a.name.toLowerCase()); // answer is something like ExAMPle.cOM and query was wWw.ExAMPle.cOM
var j = a.name.toLowerCase().lastIndexOf(domain.toLowerCase()); // answer is something like www.ExAMPle.cOM and query was ExAMPle.cOM var j = a.name.toLowerCase().lastIndexOf(domain.toLowerCase()); // answer is something like www.ExAMPle.cOM and query was ExAMPle.cOM
// it's important to note that these should only relpace changes in casing that we expected // it's important to note that these should only relpace changes in casing that we expected
// any abnormalities should be left intact to go "huh?" about // any abnormalities should be left intact to go "huh?" about
// TODO detect abnormalities? // TODO detect abnormalities?
if (-1 !== i) { if (-1 !== i) {
// "EXamPLE.cOm".replace("wWw.EXamPLE.cOm".substr(4), "www.example.com".substr(4)) // "EXamPLE.cOm".replace("wWw.EXamPLE.cOm".substr(4), "www.example.com".substr(4))
a.name = a.name.replace(casedDomain.substr(i), domain.substr(i)); a.name = a.name.replace(casedDomain.substr(i), domain.substr(i));
} else if (-1 !== j) { } else if (-1 !== j) {
// "www.example.com".replace("EXamPLE.cOm", "example.com") // "www.example.com".replace("EXamPLE.cOm", "example.com")
a.name = a.name.substr(0, j) + a.name.substr(j).replace(casedDomain, domain); a.name = a.name.substr(0, j) + a.name.substr(j).replace(casedDomain, domain);
} }
// NOTE: right now this assumes that anything matching the query matches all the way to the end // NOTE: right now this assumes that anything matching the query matches all the way to the end
// it does not handle the case of a record for example.com.uk being returned in response to a query for www.example.com correctly // it does not handle the case of a record for example.com.uk being returned in response to a query for www.example.com correctly
// (but I don't think it should need to) // (but I don't think it should need to)
if (a.name.length !== an.length) { if (a.name.length !== an.length) {
console.error("[ERROR] question / answer mismatch: '" + an + "' != '" + a.length + "'"); console.error("[ERROR] question / answer mismatch: '" + an + "' != '" + a.length + "'");
console.error(a); console.error(a);
} }
}); });
}); });
if (fail0x20) { if (fail0x20) {
console.warn(";; Warning: DNS 0x20 security not implemented (or packet spoofed). Queried '" console.warn(";; Warning: DNS 0x20 security not implemented (or packet spoofed). Queried '"
+ casedDomain + "' but got response for '" + fail0x20 + "'."); + casedDomain + "' but got response for '" + fail0x20 + "'.");
return; return;
} }
res.send({ res.send({
header: packet.header header: packet.header
, question: packet.question , question: packet.question
, answer: packet.answer , answer: packet.answer
@ -101,12 +101,12 @@ app.get('/api/dns/:domain', function (req, res, next) {
, additional: packet.additional , additional: packet.additional
, edns_options: packet.edns_options , edns_options: packet.edns_options
}); });
} }
, onListening: function () {} , onListening: function () {}
, onSent: function (/*res*/) { } , onSent: function (/*res*/) { }
, onTimeout: function (res) { , onTimeout: function (res) {
console.error('dns timeout:', res); console.error('dns timeout:', res);
next(new Error("DNS timeout - no response")); next(new Error("DNS timeout - no response"));
} }
, onClose: function () { } , onClose: function () { }
//, mdns: cli.mdns //, mdns: cli.mdns