diff --git a/README.md b/README.md index e08c929e..e25545f7 100644 --- a/README.md +++ b/README.md @@ -1217,6 +1217,9 @@ You can find more examples in the `examples` directory of this repository. * **forwardOut**(< _string_ >boundAddr, < _integer_ >boundPort, < _string_ >remoteAddr, < _integer_ >remotePort, < _function_ >callback) - _(void)_ - Alert the client of an incoming TCP connection on `boundAddr` on port `boundPort` from `remoteAddr` on port `remotePort`. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. +* **openssh_authAgent**(< _function_ >callback) - _boolean_ - Alert the client of an incoming `ssh-agent` socket connection. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. Returns `false` if you should wait for the `continue` event before sending any more traffic. + + * **openssh_forwardOutStreamLocal**(< _string_ >socketPath, < _function_ >callback) - _(void)_ - Alert the client of an incoming UNIX domain socket connection on `socketPath`. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. * **rekey**([< _function_ >callback]) - _(void)_ - Initiates a rekey with the client. If `callback` is supplied, it is added as a one-time handler for the `rekey` event. diff --git a/lib/server.js b/lib/server.js index 306d6584..a0b7a8a9 100644 --- a/lib/server.js +++ b/lib/server.js @@ -1298,6 +1298,12 @@ class Client extends EventEmitter { return this; } + + openssh_authAgent(cb) { + openChannel(this, 'auth-agent@openssh.com', cb); + return this; + } + openssh_forwardOutStreamLocal(socketPath, cb) { const opts = { socketPath }; openChannel(this, 'forwarded-streamlocal@openssh.com', opts, cb); @@ -1362,6 +1368,9 @@ function openChannel(self, type, opts, cb) { case 'x11': self._protocol.x11(localChan, initWindow, maxPacket, opts); break; + case 'auth-agent@openssh.com': + self._protocol.openssh_authAgent(localChan, initWindow, maxPacket); + break; case 'forwarded-streamlocal@openssh.com': self._protocol.openssh_forwardedStreamLocal( localChan, initWindow, maxPacket, opts diff --git a/test/test-openssh.js b/test/test-openssh.js index 67e1b860..bd405852 100644 --- a/test/test-openssh.js +++ b/test/test-openssh.js @@ -2,6 +2,9 @@ const assert = require('assert'); const { inspect } = require('util'); +const { spawn } = require('child_process'); +const net = require('net'); +const fs = require('fs'); const { fixture, @@ -16,12 +19,37 @@ const clientCfg = { username: 'foo', password: 'bar' }; const serverCfg = { hostKeys: [ fixture('ssh_host_rsa_key') ] }; { + + const agentSockPath = + process.platform === 'win32' + ? `\\\\.\\pipe\\nodejs-ssh2-test-${process.pid}` + : `${os.tmpdir()}${ + path.sep + }nodejs-ssh2-test-${process.pid}.sock`; + + if (fs.existsSync(agentSockPath)) { + fs.unlinkSync(agentSockPath); + } + + const agent = net.createServer((agentSocket) => { + assert(!agentSocket.readable, 'Agent socket not readable'); + }).listen(agentSockPath, () => { + const cleanup = () => { + server.close(() => { + if (fs.existsSync(agentSockPath)) { + fs.unlinkSync(agentSockPath); + } + }); + }; + process.on('exit', cleanup); + }); + const { client, server } = setup_( 'Exec with OpenSSH agent forwarding', { client: { ...clientCfg, - agent: '/path/to/agent', + agent: agentSockPath, }, server: serverCfg, @@ -45,8 +73,18 @@ const serverCfg = { hostKeys: [ fixture('ssh_host_rsa_key') ] }; const stream = accept(); stream.exit(100); stream.end(); - conn.end(); + + conn.openssh_authAgent(function(err, stream) { + assert(!err, `Unexpected openssh_authAgent error: ${err}`); + assert(stream.type === 'auth-agent@openssh.com', + `Unexpected openssh_authAgent channel type : ${stream.type}`); + + conn.end(); + agent.kill(); + }); + })); + })); })); }));