111 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // 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: ''
 | |
|     });
 | |
|   });
 | |
| };
 |