Skip to content

Commit daa186d

Browse files
jlordJessica Lord
authored and
Jessica Lord
committed
fix(url parser): compare srv address and parent domains
1 parent aa9871b commit daa186d

File tree

2 files changed

+128
-7
lines changed

2 files changed

+128
-7
lines changed

lib/url_parser.js

+31-7
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ module.exports = function(url, options, callback) {
2020
if (result.hostname.split('.').length < 3) {
2121
return callback(new Error('uri does not have hostname, domainname and tld'))
2222
}
23+
24+
result.domainLength = result.hostname.split('.').length;
25+
2326
if (result.pathname && result.pathname.match(',')) {
2427
return callback(new Error('invalid uri, cannot contain multiple hostnames'));
2528
}
@@ -36,17 +39,27 @@ module.exports = function(url, options, callback) {
3639
return callback(new Error('No addresses found at host'));
3740
}
3841

42+
for (var i = 0; i < addresses.length; i ++) {
43+
if (!matchesParentDomain(
44+
addresses[i].name,
45+
result.hostname,
46+
result.domainLength
47+
)) {
48+
return callback(new Error('srv record does not share hostname with parent uri'));
49+
}
50+
}
51+
52+
let connectionStrings = addresses.map(function(address, i) {
53+
if (i === 0) return `mongodb://${address.name}:${address.port}`;
54+
else return `${address.name}:${address.port}`;
55+
});
56+
57+
let connectionString = connectionStrings.join(',') + '/?';
58+
3959
dns.resolveTxt(result.host, function(err, records) {
4060
if (err && err.code !== 'ENODATA') return callback(err);
4161
if (err && err.code === 'ENODATA') records = null;
4262

43-
let connectionStrings = addresses.map(function(address, i) {
44-
if (i === 0) return `mongodb://${address.name}:${address.port}`;
45-
else return `${address.name}:${address.port}`;
46-
});
47-
48-
let connectionString = connectionStrings.join(',') + '/?';
49-
5063
if (records) {
5164
let concatRecords = records.map(function(record) {
5265
// A single record with multiple strings gets concatenated
@@ -65,6 +78,17 @@ module.exports = function(url, options, callback) {
6578
}
6679
};
6780

81+
function matchesParentDomain(srvAddress, parentDomain, domains) {
82+
let srv = srvAddress.split('.');
83+
let parent = parentDomain.split('.');
84+
for (let i = 1; i <= (domains - 1); i ++) {
85+
if (srv[srv.length - i] !== parent[parent.length - i]) {
86+
return false;
87+
}
88+
}
89+
return true;
90+
}
91+
6892
function parseHandler(address, options, callback) {
6993
let result, err;
7094
try {

test/functional/url_parser_tests.js

+97
Original file line numberDiff line numberDiff line change
@@ -1256,4 +1256,101 @@ describe('Url SRV Parser', function() {
12561256
});
12571257
}
12581258
});
1259+
1260+
/**
1261+
* @ignore
1262+
*/
1263+
it.skip("should fail because returned host name's parent (build.10gen.cc) misses 'test'", {
1264+
metadata: {
1265+
requires: { topology: ['single'] }
1266+
},
1267+
test: function(done) {
1268+
// TODO it does return 'test'
1269+
// test.build.10gen.cc
1270+
parse('mongodb+srv://test13.test.build.10gen.cc', function(err, object) {
1271+
expect(err).to.exist;
1272+
expect(err.message).to.equal('srv record does not share hostname with parent uri');
1273+
done();
1274+
});
1275+
}
1276+
});
1277+
1278+
/**
1279+
* @ignore
1280+
*/
1281+
it("should fail because returned host name's part 'not-test' mismatches URI parent part 'test'", {
1282+
metadata: {
1283+
requires: { topology: ['single'] }
1284+
},
1285+
test: function(done) {
1286+
parse('mongodb+srv://test14.test.build.10gen.cc', function(err, object) {
1287+
expect(err).to.exist;
1288+
expect(err.message).to.equal('srv record does not share hostname with parent uri');
1289+
done();
1290+
});
1291+
}
1292+
});
1293+
1294+
/**
1295+
* @ignore
1296+
*/
1297+
it("should fail because returned host name's part 'not-build' mismatches URI parent part 'build'", {
1298+
metadata: {
1299+
requires: { topology: ['single'] }
1300+
},
1301+
test: function(done) {
1302+
parse('mongodb+srv://test15.test.build.10gen.cc', function(err, object) {
1303+
expect(err).to.exist;
1304+
expect(err.message).to.equal('srv record does not share hostname with parent uri');
1305+
done();
1306+
});
1307+
}
1308+
});
1309+
1310+
/**
1311+
* @ignore
1312+
*/
1313+
it("Should fail because returned host name's part 'not-10gen' mismatches URI parent part '10gen'", {
1314+
metadata: {
1315+
requires: { topology: ['single'] }
1316+
},
1317+
test: function(done) {
1318+
parse('mongodb+srv://test16.test.build.10gen.cc', function(err, object) {
1319+
expect(err).to.exist;
1320+
expect(err.message).to.equal('srv record does not share hostname with parent uri');
1321+
done();
1322+
});
1323+
}
1324+
});
1325+
1326+
/**
1327+
* @ignore
1328+
*/
1329+
it("should fail because returned host name's TLD 'not-cc' mismatches URI TLD 'cc'", {
1330+
metadata: {
1331+
requires: { topology: ['single'] }
1332+
},
1333+
test: function(done) {
1334+
parse('mongodb+srv://test17.test.build.10gen.cc', function(err, object) {
1335+
expect(err).to.exist;
1336+
expect(err.message).to.equal('srv record does not share hostname with parent uri');
1337+
done();
1338+
});
1339+
}
1340+
});
1341+
1342+
/**
1343+
* @ignore
1344+
*/
1345+
it('should handle a srv record with more sub domains than the parent but same root', {
1346+
metadata: {
1347+
requires: { topology: ['single'] }
1348+
},
1349+
test: function(done) {
1350+
parse('mongodb+srv://test18.test.build.10gen.cc', function(err, object) {
1351+
expect(err).to.be.null;
1352+
done();
1353+
});
1354+
}
1355+
});
12591356
});

0 commit comments

Comments
 (0)