Skip to content

Commit

Permalink
fix(url parser): compare srv address and parent domains
Browse files Browse the repository at this point in the history
  • Loading branch information
jlord authored and Jessica Lord committed Nov 20, 2017
1 parent aa9871b commit daa186d
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 7 deletions.
38 changes: 31 additions & 7 deletions lib/url_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ module.exports = function(url, options, callback) {
if (result.hostname.split('.').length < 3) {
return callback(new Error('uri does not have hostname, domainname and tld'))
}

result.domainLength = result.hostname.split('.').length;

if (result.pathname && result.pathname.match(',')) {
return callback(new Error('invalid uri, cannot contain multiple hostnames'));
}
Expand All @@ -36,17 +39,27 @@ module.exports = function(url, options, callback) {
return callback(new Error('No addresses found at host'));
}

for (var i = 0; i < addresses.length; i ++) {
if (!matchesParentDomain(
addresses[i].name,
result.hostname,
result.domainLength
)) {
return callback(new Error('srv record does not share hostname with parent uri'));
}
}

let connectionStrings = addresses.map(function(address, i) {
if (i === 0) return `mongodb://${address.name}:${address.port}`;
else return `${address.name}:${address.port}`;
});

let connectionString = connectionStrings.join(',') + '/?';

dns.resolveTxt(result.host, function(err, records) {
if (err && err.code !== 'ENODATA') return callback(err);
if (err && err.code === 'ENODATA') records = null;

let connectionStrings = addresses.map(function(address, i) {
if (i === 0) return `mongodb://${address.name}:${address.port}`;
else return `${address.name}:${address.port}`;
});

let connectionString = connectionStrings.join(',') + '/?';

if (records) {
let concatRecords = records.map(function(record) {
// A single record with multiple strings gets concatenated
Expand All @@ -65,6 +78,17 @@ module.exports = function(url, options, callback) {
}
};

function matchesParentDomain(srvAddress, parentDomain, domains) {
let srv = srvAddress.split('.');
let parent = parentDomain.split('.');
for (let i = 1; i <= (domains - 1); i ++) {
if (srv[srv.length - i] !== parent[parent.length - i]) {
return false;
}
}
return true;
}

function parseHandler(address, options, callback) {
let result, err;
try {
Expand Down
97 changes: 97 additions & 0 deletions test/functional/url_parser_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1256,4 +1256,101 @@ describe('Url SRV Parser', function() {
});
}
});

/**
* @ignore
*/
it.skip("should fail because returned host name's parent (build.10gen.cc) misses 'test'", {
metadata: {
requires: { topology: ['single'] }
},
test: function(done) {
// TODO it does return 'test'
// test.build.10gen.cc
parse('mongodb+srv://test13.test.build.10gen.cc', function(err, object) {
expect(err).to.exist;
expect(err.message).to.equal('srv record does not share hostname with parent uri');
done();
});
}
});

/**
* @ignore
*/
it("should fail because returned host name's part 'not-test' mismatches URI parent part 'test'", {
metadata: {
requires: { topology: ['single'] }
},
test: function(done) {
parse('mongodb+srv://test14.test.build.10gen.cc', function(err, object) {
expect(err).to.exist;
expect(err.message).to.equal('srv record does not share hostname with parent uri');
done();
});
}
});

/**
* @ignore
*/
it("should fail because returned host name's part 'not-build' mismatches URI parent part 'build'", {
metadata: {
requires: { topology: ['single'] }
},
test: function(done) {
parse('mongodb+srv://test15.test.build.10gen.cc', function(err, object) {
expect(err).to.exist;
expect(err.message).to.equal('srv record does not share hostname with parent uri');
done();
});
}
});

/**
* @ignore
*/
it("Should fail because returned host name's part 'not-10gen' mismatches URI parent part '10gen'", {
metadata: {
requires: { topology: ['single'] }
},
test: function(done) {
parse('mongodb+srv://test16.test.build.10gen.cc', function(err, object) {
expect(err).to.exist;
expect(err.message).to.equal('srv record does not share hostname with parent uri');
done();
});
}
});

/**
* @ignore
*/
it("should fail because returned host name's TLD 'not-cc' mismatches URI TLD 'cc'", {
metadata: {
requires: { topology: ['single'] }
},
test: function(done) {
parse('mongodb+srv://test17.test.build.10gen.cc', function(err, object) {
expect(err).to.exist;
expect(err.message).to.equal('srv record does not share hostname with parent uri');
done();
});
}
});

/**
* @ignore
*/
it('should handle a srv record with more sub domains than the parent but same root', {
metadata: {
requires: { topology: ['single'] }
},
test: function(done) {
parse('mongodb+srv://test18.test.build.10gen.cc', function(err, object) {
expect(err).to.be.null;
done();
});
}
});
});

0 comments on commit daa186d

Please sign in to comment.