// TODO: differentiate between auth types (i.e., MIT-MAGIC-COOKIE-1 and XDM-AUTHORIZATION-1) // and choose the best based on the algorithm in libXau's XauGetBestAuthByAddr var fs = Require('fs'); var Buffer = Require('buffer').Buffer; // add 'unpack' method for buffer Require('x11/core/unpackbuffer').addUnpack(Buffer); var typeToName = { 256: 'Local', 65535: 'Wild', 254: 'Netname', 253: 'Krb5Principal', 252: 'LocalHost', 0: 'Internet', 1: 'DECnet', 2: 'Chaos', 5: 'ServerInterpreted', 6: 'Internet6' }; function parseXauth( buf ) { var offset = 0; var auth = []; var cookieProperties = ['address', 'display', 'authName', 'authData']; while (offset < buf.length) { var cookie = {}; cookie.type = buf.readUInt16BE(offset); if (!typeToName[cookie.type]) { console.warn('Unknown address type'); } offset += 2; cookieProperties.forEach(function(property) { var length = buf.unpack('n', offset)[0]; offset += 2; if (cookie.type === 0 && property == 'address') { // Internet // 4 bytes of ip addess, convert to w.x.y.z string cookie.address = [ buf[offset], buf[offset+1], buf[offset+2], buf[offset+3]] .map(function(octet) { return octet.toString(10) }).join('.'); } else { cookie[property] = buf.unpackString(length, offset); } offset += length; }); auth.push(cookie); } return auth; } var homedir = Require('os/os-homedir'); var path = Require('path'); function readXauthority(cb) { var filename = process.env.XAUTHORITY || path.join(homedir(), '.Xauthority'); fs.readFile(filename, function(err, data) { if (!err) return cb(null, data); if(err.code == 'ENOENT') { // Xming/windows uses %HOME%/Xauthority ( .Xauthority with no dot ) - try with this name filename = process.env.XAUTHORITY || path.join(homedir(), 'Xauthority'); fs.readFile(filename, function (err, data) { if (err.code == 'ENOENT') { cb(null, null); } else { cb(err); } }); } else { cb(err); } }); } module.exports = function( display, host, socketFamily, cb ) { var family; if (socketFamily === 'IPv4') { family = 0; // Internet } else if (socketFamily === 'IPv6') { family = 6; // Internet6 } else { family = 256; // Local } readXauthority(function(err, data) { if(err) return cb(err); if (!data) { return cb(null, { authName: '', authData: '' }); } var auth = parseXauth(data); for (var cookieNum in auth) { var cookie = auth[cookieNum]; if ((typeToName[cookie.family] === 'Wild' || (cookie.type === family && cookie.address === host)) && (cookie.display.length === 0 || cookie.display === display)) return cb( null, cookie ); } // If no cookie is found, proceed without authentication cb(null, { authName: '', authData: '' }); }); };