262 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			262 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | var http = require('http'); | ||
|  | var https = require('https'); | ||
|  | var net = require('net'); | ||
|  | var fs = require('fs'); | ||
|  | var path = require('path'); | ||
|  | var should = require('should'); | ||
|  | var tunnel = require('../index'); | ||
|  | 
 | ||
|  | function readPem(file) { | ||
|  |   return fs.readFileSync(path.join('test/keys', file + '.pem')); | ||
|  | } | ||
|  | 
 | ||
|  | var serverKey = readPem('server2-key'); | ||
|  | var serverCert = readPem('server2-cert'); | ||
|  | var serverCA = readPem('ca1-cert'); | ||
|  | var proxyKey = readPem('proxy2-key'); | ||
|  | var proxyCert = readPem('proxy2-cert'); | ||
|  | var proxyCA = readPem('ca2-cert'); | ||
|  | var client1Key = readPem('client1-key'); | ||
|  | var client1Cert = readPem('client1-cert'); | ||
|  | var client1CA = readPem('ca3-cert'); | ||
|  | var client2Key = readPem('client2-key'); | ||
|  | var client2Cert = readPem('client2-cert'); | ||
|  | var client2CA = readPem('ca4-cert'); | ||
|  | 
 | ||
|  | describe('HTTPS over HTTPS authentication failed', function() { | ||
|  |   it('should finish without error', function(done) { | ||
|  |     var serverPort = 3008; | ||
|  |     var proxyPort = 3009; | ||
|  |     var serverConnect = 0; | ||
|  |     var proxyConnect = 0; | ||
|  |     var clientRequest = 0; | ||
|  |     var clientConnect = 0; | ||
|  |     var clientError = 0; | ||
|  |     var server; | ||
|  |     var proxy; | ||
|  | 
 | ||
|  |     server = https.createServer({ | ||
|  |       key: serverKey, | ||
|  |       cert: serverCert, | ||
|  |       ca: [client1CA], | ||
|  |       requestCert: true, | ||
|  |       rejectUnauthorized: true | ||
|  |     }, function(req, res) { | ||
|  |       tunnel.debug('SERVER: got request', req.url); | ||
|  |       ++serverConnect; | ||
|  |       req.on('data', function(data) { | ||
|  |       }); | ||
|  |       req.on('end', function() { | ||
|  |         res.writeHead(200); | ||
|  |         res.end('Hello, ' + serverConnect); | ||
|  |         tunnel.debug('SERVER: sending response'); | ||
|  |       }); | ||
|  |       req.resume(); | ||
|  |     }); | ||
|  |     //server.addContext('server2', {
 | ||
|  |     //  key: serverKey,
 | ||
|  |     //  cert: serverCert,
 | ||
|  |     //  ca: [client1CA],
 | ||
|  |     //});
 | ||
|  |     server.listen(serverPort, setupProxy); | ||
|  | 
 | ||
|  |     function setupProxy() { | ||
|  |       proxy = https.createServer({ | ||
|  |         key: proxyKey, | ||
|  |         cert: proxyCert, | ||
|  |         ca: [client2CA], | ||
|  |         requestCert: true, | ||
|  |         rejectUnauthorized: true | ||
|  |       }, function(req, res) { | ||
|  |         should.fail(); | ||
|  |       }); | ||
|  |       //proxy.addContext('proxy2', {
 | ||
|  |       //  key: proxyKey,
 | ||
|  |       //  cert: proxyCert,
 | ||
|  |       //  ca: [client2CA],
 | ||
|  |       //});
 | ||
|  |       proxy.on('upgrade', onConnect); // for v0.6
 | ||
|  |       proxy.on('connect', onConnect); // for v0.7 or later
 | ||
|  | 
 | ||
|  |       function onConnect(req, clientSocket, head) { | ||
|  |         req.method.should.equal('CONNECT'); | ||
|  |         req.url.should.equal('localhost:' + serverPort); | ||
|  |         req.headers.should.not.have.property('transfer-encoding'); | ||
|  |         ++proxyConnect; | ||
|  | 
 | ||
|  |         var serverSocket = net.connect(serverPort, function() { | ||
|  |           tunnel.debug('PROXY: replying to client CONNECT request'); | ||
|  |           clientSocket.write('HTTP/1.1 200 Connection established\r\n\r\n'); | ||
|  |           clientSocket.pipe(serverSocket); | ||
|  |           serverSocket.write(head); | ||
|  |           serverSocket.pipe(clientSocket); | ||
|  |           // workaround, see #2524
 | ||
|  |           serverSocket.on('end', function() { | ||
|  |             clientSocket.end(); | ||
|  |           }); | ||
|  |         }); | ||
|  |       } | ||
|  |       proxy.listen(proxyPort, setupClient); | ||
|  |     } | ||
|  | 
 | ||
|  |     function setupClient() { | ||
|  |       function doRequest(name, options, host) { | ||
|  |         tunnel.debug('CLIENT: Making HTTPS request (%s)', name); | ||
|  |         ++clientRequest; | ||
|  |         var agent = tunnel.httpsOverHttps(options); | ||
|  |         var req = https.get({ | ||
|  |           host: 'localhost', | ||
|  |           port: serverPort, | ||
|  |           path: '/' + encodeURIComponent(name), | ||
|  |           headers: { | ||
|  |             host: host ? host : 'localhost', | ||
|  |           }, | ||
|  |           rejectUnauthorized: true, | ||
|  |           agent: agent | ||
|  |         }, function(res) { | ||
|  |           tunnel.debug('CLIENT: got HTTPS response (%s)', name); | ||
|  |           ++clientConnect; | ||
|  |           res.on('data', function(data) { | ||
|  |           }); | ||
|  |           res.on('end', function() { | ||
|  |             req.emit('finish'); | ||
|  |           }); | ||
|  |           res.resume(); | ||
|  |         }); | ||
|  |         req.on('error', function(err) { | ||
|  |           tunnel.debug('CLIENT: failed HTTP response (%s)', name, err); | ||
|  |           ++clientError; | ||
|  |           req.emit('finish'); | ||
|  |         }); | ||
|  |         req.on('finish', function() { | ||
|  |           if (clientConnect + clientError === clientRequest) { | ||
|  |             proxy.close(); | ||
|  |             server.close(); | ||
|  |           } | ||
|  |         }); | ||
|  |       } | ||
|  | 
 | ||
|  |       doRequest('no cert origin nor proxy', { // invalid
 | ||
|  |         maxSockets: 1, | ||
|  |         ca: [serverCA], | ||
|  |         rejectUnauthorized: true, | ||
|  |         // no certificate for origin server
 | ||
|  |         proxy: { | ||
|  |           port: proxyPort, | ||
|  |           ca: [proxyCA], | ||
|  |           rejectUnauthorized: true, | ||
|  |           headers: { | ||
|  |             host: 'proxy2' | ||
|  |           } | ||
|  |           // no certificate for proxy
 | ||
|  |         } | ||
|  |       }, 'server2'); | ||
|  | 
 | ||
|  |       doRequest('no cert proxy', { // invalid
 | ||
|  |         maxSockets: 1, | ||
|  |         ca: [serverCA], | ||
|  |         rejectUnauthorized: true, | ||
|  |         // client certification for origin server
 | ||
|  |         key: client1Key, | ||
|  |         cert: client1Cert, | ||
|  |         proxy: { | ||
|  |           port: proxyPort, | ||
|  |           ca: [proxyCA], | ||
|  |           rejectUnauthorized: true, | ||
|  |           headers: { | ||
|  |             host: 'proxy2' | ||
|  |           } | ||
|  |           // no certificate for proxy
 | ||
|  |         } | ||
|  |       }, 'server2'); | ||
|  | 
 | ||
|  |       doRequest('no cert origin', { // invalid
 | ||
|  |         maxSockets: 1, | ||
|  |         ca: [serverCA], | ||
|  |         rejectUnauthorized: true, | ||
|  |         // no certificate for origin server
 | ||
|  |         proxy: { | ||
|  |           port: proxyPort, | ||
|  |           servername: 'proxy2', | ||
|  |           ca: [proxyCA], | ||
|  |           rejectUnauthorized: true, | ||
|  |           headers: { | ||
|  |             host: 'proxy2' | ||
|  |           }, | ||
|  |           // client certification for proxy
 | ||
|  |           key: client2Key, | ||
|  |           cert: client2Cert | ||
|  |         } | ||
|  |       }, 'server2'); | ||
|  | 
 | ||
|  |       doRequest('invalid proxy server name', { // invalid
 | ||
|  |         maxSockets: 1, | ||
|  |         ca: [serverCA], | ||
|  |         rejectUnauthorized: true, | ||
|  |         // client certification for origin server
 | ||
|  |         key: client1Key, | ||
|  |         cert: client1Cert, | ||
|  |         proxy: { | ||
|  |           port: proxyPort, | ||
|  |           ca: [proxyCA], | ||
|  |           rejectUnauthorized: true, | ||
|  |           // client certification for proxy
 | ||
|  |           key: client2Key, | ||
|  |           cert: client2Cert, | ||
|  |         } | ||
|  |       }, 'server2'); | ||
|  | 
 | ||
|  |       doRequest('invalid origin server name', { // invalid
 | ||
|  |         maxSockets: 1, | ||
|  |         ca: [serverCA], | ||
|  |         rejectUnauthorized: true, | ||
|  |         // client certification for origin server
 | ||
|  |         key: client1Key, | ||
|  |         cert: client1Cert, | ||
|  |         proxy: { | ||
|  |           port: proxyPort, | ||
|  |           servername: 'proxy2', | ||
|  |           ca: [proxyCA], | ||
|  |           rejectUnauthorized: true, | ||
|  |           headers: { | ||
|  |             host: 'proxy2' | ||
|  |           }, | ||
|  |           // client certification for proxy
 | ||
|  |           key: client2Key, | ||
|  |           cert: client2Cert | ||
|  |         } | ||
|  |       }); | ||
|  | 
 | ||
|  |       doRequest('valid', { // valid
 | ||
|  |         maxSockets: 1, | ||
|  |         ca: [serverCA], | ||
|  |         rejectUnauthorized: true, | ||
|  |         // client certification for origin server
 | ||
|  |         key: client1Key, | ||
|  |         cert: client1Cert, | ||
|  |         proxy: { | ||
|  |           port: proxyPort, | ||
|  |           servername: 'proxy2', | ||
|  |           ca: [proxyCA], | ||
|  |           rejectUnauthorized: true, | ||
|  |           headers: { | ||
|  |             host: 'proxy2' | ||
|  |           }, | ||
|  |           // client certification for proxy
 | ||
|  |           key: client2Key, | ||
|  |           cert: client2Cert | ||
|  |         } | ||
|  |       }, 'server2'); | ||
|  |     } | ||
|  | 
 | ||
|  |     server.on('close', function() { | ||
|  |       serverConnect.should.equal(1); | ||
|  |       proxyConnect.should.equal(3); | ||
|  |       clientConnect.should.equal(1); | ||
|  |       clientError.should.equal(5); | ||
|  | 
 | ||
|  |       done(); | ||
|  |     }); | ||
|  |   }); | ||
|  | }); |