Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ssh2

Package Overview
Dependencies
Maintainers
1
Versions
105
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ssh2 - npm Package Compare versions

Comparing version 0.1.3 to 0.1.4

6

lib/agent.js

@@ -24,3 +24,3 @@ var Socket = require('net').Socket;

sock.on('connect', function() {
sock.once('connect', function() {
var buf;

@@ -155,6 +155,6 @@ if (isSigning) {

});
sock.on('error', function(err) {
sock.once('error', function(err) {
error = err;
});
sock.on('close', function(had_err) {
sock.once('close', function(had_err) {
if (error)

@@ -161,0 +161,0 @@ cb(error);

@@ -7,3 +7,4 @@ var inherits = require('util').inherits,

var MAX_WINDOW = Math.pow(2, 32) - 1,
var MAX_WINDOW = 0x100000, // 1MB (protocol supports up to Math.pow(2, 32) - 1)
WINDOW_THRESH = MAX_WINDOW / 2,
SIGNALS = ['ABRT', 'ALRM', 'FPE', 'HUP', 'ILL', 'INT', 'KILL', 'PIPE',

@@ -38,3 +39,3 @@ 'QUIT', 'SEGV', 'TERM', 'USR1', 'USR2'],

conn._parser.on('CHANNEL_EOF:' + this.incoming.id, function() {
conn._parser.once('CHANNEL_EOF:' + this.incoming.id, function() {
self.incoming.state = 'eof';

@@ -48,3 +49,3 @@ if (self._stream) {

conn._parser.on('CHANNEL_CLOSE:' + this.incoming.id, function() {
conn._parser.once('CHANNEL_CLOSE:' + this.incoming.id, function() {
self.incoming.state = 'closed';

@@ -64,2 +65,5 @@ if (self.outgoing.state === 'open' || self.outgoing.state === 'eof')

conn._parser.on('CHANNEL_DATA:' + this.incoming.id, function(data) {
self.incoming.window -= data.length;
if (self.incoming.window <= WINDOW_THRESH)
self._sendWndAdjust();
if (self._stream) {

@@ -74,2 +78,5 @@ if (self._stream._decoder)

function(type, data) {
self.incoming.window -= data.length;
if (self.incoming.window <= WINDOW_THRESH)
self._sendWndAdjust();
if (self._stream) {

@@ -84,2 +91,11 @@ if (self._stream._decoder)

conn._parser.on('CHANNEL_WINDOW_ADJUST:' + this.incoming.id, function(amt) {
// the server is allowing us to send `amt` more bytes of data
self.outgoing.window += amt;
if (self._stream && self._stream.outpaused) {
self._stream.outpaused = false;
self._stream._drainOutBuffer();
}
});
conn._parser.on('CHANNEL_SUCCESS:' + this.incoming.id, function() {

@@ -348,2 +364,3 @@ if (self._callbacks.length)

Channel.prototype._sendSubsystem = function(name, cb) {
// Note: CHANNEL_REQUEST does not consume window space
/*

@@ -381,6 +398,8 @@ byte SSH_MSG_CHANNEL_REQUEST

while (len - p > 0) {
if (this.outgoing.window === 0)
this._sendWndAdjust();
sliceLen = (len - p < this.outgoing.window ? len - p : this.outgoing.window);
while (len - p > 0 && this.outgoing.window > 0) {
sliceLen = len - p;
if (sliceLen > this.outgoing.window)
sliceLen = this.outgoing.window;
if (sliceLen > this.outgoing.packetSize)
sliceLen = this.outgoing.packetSize;
if (extendedType === undefined) {

@@ -417,2 +436,18 @@ /*

// Will we ever be in a "good" state and be sending data without a
// ChannelStream?
if (len - p > 0 && this._stream) {
// buffer outbound data until server sends us a CHANNEL_WINDOW_ADJUST message
if (p > 0) {
// partial
buf = new Buffer(len - p);
data.copy(buf, 0, p);
this._stream._outbuffer.push([buf, extendedType]);
} else
this._stream._outbuffer.push([data, extendedType]);
if (ret)
ret = false;
this._stream.outpaused = true;
}
return ret;

@@ -427,3 +462,3 @@ };

*/
amt = amt || Math.min(MAX_WINDOW, this.outgoing.packetSize);
amt = amt || MAX_WINDOW;
var buf = new Buffer(1 + 4 + 4);

@@ -434,3 +469,3 @@ buf[0] = MESSAGE.CHANNEL_WINDOW_ADJUST;

this.outgoing.window += amt;
this.incoming.window += amt;

@@ -448,3 +483,2 @@ return this._conn._send(buf);

function ChannelStream(channel) {
// TODO: update readable and writable appropriately
var self = this;

@@ -454,11 +488,13 @@ this.readable = true;

this.paused = false;
this.outpaused = false;
this.allowHalfOpen = false;
this._channel = channel;
this._buffer = [];
this._outbuffer = [];
this._inbuffer = [];
this._decoder = undefined;
channel._conn._sock.on('end', function() {
channel._conn._sock.once('end', function() {
self.writable = false;
self.readable = false;
});
channel._conn._sock.on('close', function() {
channel._conn._sock.once('close', function() {
self.writable = false;

@@ -470,3 +506,96 @@ self.readable = false;

ChannelStream.prototype._emit = ChannelStream.prototype.emit;
ChannelStream.prototype.emit = function(ev, arg1, arg2, arg3, arg4, arg5) {
if (this.paused) {
if (arg1 === undefined)
this._inbuffer.push([ev]);
else if (arg2 === undefined)
this._inbuffer.push([ev, arg1]);
else if (arg3 === undefined)
this._inbuffer.push([ev, arg1, arg2]);
else if (arg4 === undefined)
this._inbuffer.push([ev, arg1, arg2, arg3]);
else if (arg5 === undefined)
this._inbuffer.push([ev, arg1, arg2, arg3, arg4]);
else
this._inbuffer.push([ev, arg1, arg2, arg3, arg4, arg5]);
} else {
if (ev === 'data' && this._decoder)
this._emit(ev, this._decoder.write(arg1), arg2);
else if (arg1 === undefined)
this._emit(ev);
else if (arg2 === undefined)
this._emit(ev, arg1);
else if (arg3 === undefined)
this._emit(ev, arg1, arg2);
else if (arg4 === undefined)
this._emit(ev, arg1, arg2, arg3);
else if (arg5 === undefined)
this._emit(ev, arg1, arg2, arg3, arg4);
else
this._emit(ev, arg1, arg2, arg3, arg4, arg5);
}
};
ChannelStream.prototype._drainInBuffer = function() {
var i = 0, val, vallen, len = this._inbuffer.length, ret;
for (; i < len; ++i) {
val = this._inbuffer[i];
vallen = val.length;
if (val[0] === 'data' && this._decoder)
this._emit(val[0], this._decoder.write(val[1]), val[2]);
else if (vallen === 1)
this._emit(val[0]);
else if (vallen === 2)
this._emit(val[0], val[1]);
else if (vallen === 3)
this._emit(val[0], val[1], val[2]);
else if (vallen === 4)
this._emit(val[0], val[1], val[2], val[3]);
else if (vallen === 5)
this._emit(val[0], val[1], val[2], val[3], val[4]);
else
this._emit(val[0], val[1], val[2], val[3], val[4], val[5]);
}
};
ChannelStream.prototype._drainOutBuffer = function() {
if (!this.writable)
return;
var i = 0, len = this._outbuffer.length, ret = true;
for (; i < len; ++i) {
if (this._outbuffer[i] === null) {
// end() was called
ret = true;
len = 0; // bypass length check
this.destroy();
break;
} else if (this.outpaused)
break;
else
ret = this._channel._sendData(this._outbuffer[i][0], this._outbuffer[i][1]);
}
// it's possible _sendData pushed more data into the outbuffer if we ran out
// of window space while in the above for-loop. we check for that here ...
if (len === this._outbuffer.length) {
if (len)
this._outbuffer = [];
} else {
this._outbuffer.splice(0, i);
ret = false;
}
if (ret)
this.emit('drain');
return ret;
};
ChannelStream.prototype.write = function(data, encoding, extended) {
if (!this.writable)
throw new Error('ChannelStream is not writable');
var extendedType;

@@ -490,4 +619,4 @@

if (this.paused) {
this._buffer.push([data, extended]);
if (this.outpaused) {
this._outbuffer.push([data, extended]);
return false;

@@ -511,21 +640,3 @@ } else {

this.paused = false;
var i = 0, len = this._buffer.length, ret;
for (; i < len; ++i) {
if (this._buffer[i] === null) {
ret = this._channel.eof();
ret = this._channel.close();
this.writable = false;
this.readable = false;
break;
} else
ret = this._channel._sendData(this._buffer[i][0], this._buffer[i][1]);
}
if (len)
this._buffer = [];
if (ret === true)
this.emit('drain');
this._drainInBuffer();
this._channel._conn._sock.resume();

@@ -535,7 +646,9 @@ };

ChannelStream.prototype.end = function(data, encoding, extended) {
if (!this.writable)
return;
var ret;
if (data && data.length)
ret = this.write(data, encoding, extended);
if (this.paused) {
ret = this._buffer.push(null);
if (this.outpaused) {
ret = this._outbuffer.push(null);
this.resume();

@@ -555,7 +668,14 @@ } else {

ChannelStream.prototype.destroy = function() {
this._channel.eof();
this._channel.close();
this._buffer = [];
var ret;
ret = this._channel.eof();
ret = this._channel.close();
if (this._outbuffer.length)
this._outbuffer = [];
if (this._inbuffer.length)
this._inbuffer = [];
this.writable = false;
this.readable = false;
this.paused = false;
this.outpaused = false;
return ret;
};

@@ -562,0 +682,0 @@

@@ -24,3 +24,4 @@ var net = require('net'),

DISCONNECT_REASON = consts.DISCONNECT_REASON,
CHANNEL_OPEN_FAILURE = consts.CHANNEL_OPEN_FAILURE;
CHANNEL_OPEN_FAILURE = consts.CHANNEL_OPEN_FAILURE,
PING_PACKET = new Buffer([MESSAGE.IGNORE, 0, 0, 0, 0]);

@@ -307,2 +308,3 @@ function isStreamCipher(cipher) {

}
// verify the host fingerprint first if needed
if (self._state === 'initexchg' && self._fingerprint && self._cbfingerprint) {

@@ -327,3 +329,3 @@ var hostHash = require('crypto').createHash(self._fingerprint);

info.secret = new Buffer(compSecret, 'binary');
// SHA1 for both currently supported DH kex methods
// SHA1 for supported DH group1 and group14 kex methods
var hash = crypto.createHash('sha1');

@@ -645,3 +647,3 @@ var len_ident = Buffer.byteLength(SSH_IDENT),

if (self._state === 'initexchg') {
// attempt to begin to perform user auth
// begin to perform user auth
var svcBuf = new Buffer(1 + 4 + 12);

@@ -654,2 +656,4 @@ svcBuf[0] = MESSAGE.SERVICE_REQUEST;

self._state = 'authenticated';
// empty our outbound buffer of any data we tried to send while the key
// re-exchange was happening
var b = 0, blen = self._buffer.length;

@@ -670,2 +674,4 @@ for (; b < blen; ++b) {

this._parser.on('SERVICE_ACCEPT', function(svc) {
// we previously sent a request to start the process of user authentication
// and the server is allowing us to continue
if (svc === 'ssh-userauth') {

@@ -682,2 +688,3 @@ if (self._password)

this._parser.on('USERAUTH_SUCCESS', function() {
// we successfully authenticated with the server
self._state = 'authenticated';

@@ -691,2 +698,8 @@ if (self._parser._authMethod === 'password'

self._agentKeys = undefined;
if (typeof self._pingInterval === 'number') {
self._pinger = setInterval(function() {
self._ping();
}, self._pingInterval);
}
self.emit('ready');

@@ -696,2 +709,3 @@ });

this._parser.on('USERAUTH_FAILURE', function(auths, partial) {
// we failed to authenticate with the server for whatever reason
if (self._parser._authMethod === 'password'

@@ -709,2 +723,4 @@ && self._parser._newpwd !== undefined) {

this._parser.on('USERAUTH_BANNER', function(message, lang) {
// the server sent us a notice/banner of some kind for the user to read
// before attempting to log in, usually a legal notice or some such
self.emit('banner', message, lang);

@@ -714,2 +730,4 @@ });

this._parser.on('USERAUTH_PASSWD_CHANGEREQ', function(message, lang) {
// we tried to authenticate via password, but the server says we need to
// change our password first
self._parser._newpwd = undefined;

@@ -728,2 +746,4 @@ self.emit('change password', message, lang, function(newpwd) {

this._parser.on('USERAUTH_INFO_REQUEST', function(name, inst, lang, prompts) {
// we sent a keyboard-interactive user authentication request and now the
// server is sending us the prompts we need to present to the user
self.emit('keyboard-interactive', name, inst, lang, prompts,

@@ -760,2 +780,5 @@ function(answers) {

this._parser.on('USERAUTH_PK_OK', function() {
// server says our public key is permitted for user authentication, so
// continue on with real user authentication request
// (signing data with private key)
self._authPK(true);

@@ -765,2 +788,4 @@ });

this._parser.on('REQUEST_SUCCESS', function(data) {
// general success response -- one of two replies sent when a packet's
// "want_reply" is set to true
if (self._callbacks.length)

@@ -771,2 +796,4 @@ self._callbacks.shift()(false, data);

this._parser.on('REQUEST_FAILURE', function() {
// general failure response -- one of two replies sent when a packet's
// "want_reply" is set to true
if (self._callbacks.length)

@@ -777,2 +804,5 @@ self._callbacks.shift()(true);

this._parser.on('CHANNEL_OPEN', function(info) {
// the server is trying to open a channel with us, this is usually when
// we asked the server to forward us connections on some port and now they
// are asking us to accept/deny an incoming connection on their side
if (info.type === 'forwarded-tcpip') {

@@ -792,5 +822,2 @@ var rejectConn = false, localChan;

if (rejectConn)
reject();
// TODO: automatic rejection after some timeout?

@@ -857,2 +884,5 @@ var accept = function() {

if (rejectConn)
reject();
if (localChan !== false)

@@ -895,2 +925,3 @@ self.emit('tcp connection', info.data, accept, reject);

this._agent = opts.agent; // process.env.SSH_AUTH_SOCK
this._pingInterval = opts.pingInterval;

@@ -913,2 +944,3 @@ this._sock = new net.Socket();

this._sessionid = undefined;
this._pinger = undefined;

@@ -997,2 +1029,3 @@ this._curChan = -1;

if (!this._privateKey.public) {
// we get here if we didn't load a PuTTY key file
if (this._publicKey) {

@@ -1007,2 +1040,3 @@ keyInfo = keyParser(this._publicKey);

} else {
// parsing private key in ASN.1 format
var i = 2, len, octets,

@@ -1168,3 +1202,3 @@ privKey = this._privateKey.private,

this._sock.on('connect', function() {
this._sock.once('connect', function() {
self._state = 'initexchg';

@@ -1177,11 +1211,19 @@ self.emit('connect');

});
this._sock.on('error', function(err) {
this._sock.once('error', function(err) {
err.level = 'connection-socket';
self.emit('error', err);
});
this._sock.on('end', function() {
this._sock.once('end', function() {
if (self._pinger) {
clearInterval(self._pinger);
self._pinger = undefined;
}
self._state = 'closed';
self.emit('end');
});
this._sock.on('close', function(had_err) {
this._sock.once('close', function(had_err) {
if (self._pinger) {
clearInterval(self._pinger);
self._pinger = undefined;
}
self._parser.reset();

@@ -1200,2 +1242,3 @@ self._state = 'closed';

Connection.prototype.exec = function(cmd, env, cb) {
// execute an arbitrary command on the server
if (typeof env === 'function') {

@@ -1216,2 +1259,3 @@ cb = env;

Connection.prototype.shell = function(window, cb) {
// start an interactive terminal/shell session
var rows = 24, cols = 80, width = 640, height = 480, term = 'vt100';

@@ -1245,2 +1289,4 @@

Connection.prototype.forwardIn = function(address, port, cb) {
// send a request for the server to start forwarding TCP connections to us
// on a particular address and port
/*

@@ -1284,2 +1330,4 @@ byte SSH_MSG_GLOBAL_REQUEST

Connection.prototype.unforwardIn = function(address, port, cb) {
// send a request to stop forwarding traffic from the server to us for a
// particular address and port
/*

@@ -1314,2 +1362,3 @@ byte SSH_MSG_GLOBAL_REQUEST

Connection.prototype.forwardOut = function(srcIP, srcPort, dstIP, dstPort, cb) {
// send a request to forward a TCP connection to the server
/*

@@ -1348,2 +1397,3 @@ byte SSH_MSG_CHANNEL_OPEN

Connection.prototype.sftp = function(cb) {
// start an SFTP session
return this._openChan('session', function(err, chan) {

@@ -1365,3 +1415,3 @@ if (err)

});
sftp.on('close', function() {
sftp.once('close', function() {
stream.end();

@@ -1378,4 +1428,8 @@ });

Connection.prototype._openChan = function(type, blob, cb) {
// ask the server to open a channel for some purpose (e.g. session (sftp, exec,
// terminal), or forwarding a TCP connection to the server)
var self = this,
localChan = this._nextChan();
localChan = this._nextChan(),
inWindow = Channel.MAX_WINDOW,
inPktSize = Channel.MAX_WINDOW;

@@ -1398,4 +1452,4 @@ if (localChan === false)

id: localChan,
window: Channel.MAX_WINDOW,
packetSize: Channel.MAX_WINDOW,
window: inWindow,
packetSize: inPktSize,
state: 'open'

@@ -1437,4 +1491,4 @@ },

buf.writeUInt32BE(localChan, p, true);
buf.writeUInt32BE(Channel.MAX_WINDOW, p += 4, true);
buf.writeUInt32BE(Channel.MAX_WINDOW, p += 4, true);
buf.writeUInt32BE(inWindow, p += 4, true);
buf.writeUInt32BE(inPktSize, p += 4, true);
if (blob)

@@ -1447,2 +1501,5 @@ blob.copy(buf, p += 4);

Connection.prototype._nextChan = function() {
// get the next available channel number
// optimized path
if (this._curChan < MAX_CHANNEL)

@@ -1452,2 +1509,3 @@ if (++this._curChan <= MAX_CHANNEL)

// slower lookup path
for (var i = 0; i < MAX_CHANNEL; ++i)

@@ -1460,3 +1518,11 @@ if (this._channels.indexOf(i))

Connection.prototype._ping = function() {
// simply send an SSH_MSG_IGNORE message for pinging purposes
this._send(PING_PACKET);
};
Connection.prototype._tryNextAuth = function(noAgent) {
// try the next user authentication mechanism:
// for ssh-agent users, this means the next public key stored in ssh-agent.
// otherwise possibly try keyboard-interactive before erroring out
if (this._agent && !noAgent)

@@ -1479,2 +1545,3 @@ this._authAgent();

Connection.prototype._authPwd = function(newpwd) {
// attempt to authenticate via password
/*

@@ -1533,2 +1600,3 @@ "Normal" password auth:

Connection.prototype._authKeyboard = function() {
// attempt to authenticate via keyboard-interactive
/*

@@ -1567,2 +1635,3 @@ byte SSH_MSG_USERAUTH_REQUEST

Connection.prototype._authPK = function(sign) {
// attempt to authenticate via key
this._parser._authMethod = 'pubkey';

@@ -1724,2 +1793,3 @@ /*

Connection.prototype._authAgent = function() {
// attempt to authenticate via ssh-agent
this._parser._authMethod = 'agent';

@@ -1726,0 +1796,0 @@

@@ -540,2 +540,11 @@ // TODO: * Filter control codes from strings

break;
case MESSAGE.CHANNEL_WINDOW_ADJUST:
/*
byte SSH_MSG_CHANNEL_WINDOW_ADJUST
uint32 recipient channel
uint32 bytes to add
*/
this.emit('CHANNEL_WINDOW_ADJUST:' + payload.readUInt32BE(1, true),
payload.readUInt32BE(5, true));
break;
case MESSAGE.CHANNEL_SUCCESS:

@@ -542,0 +551,0 @@ /*

{ "name": "ssh2",
"version": "0.1.3",
"version": "0.1.4",
"author": "Brian White <mscdex@mscdex.net>",

@@ -4,0 +4,0 @@ "description": "An SSH2 client module written in pure JavaScript for node.js",

@@ -390,2 +390,4 @@

* **pingInterval** - < _integer_ > - How often to send SSH-level keepalive packets to the server. **Default:** (no keepalive)
* **exec**(< _string_ >command[, < _object_ >environment], < _function_ >callback) - _(void)_ - Executes `command` on the server, with an optional `environment` set before execution. `callback` has 2 parameters: < _Error_ >err, < _ChannelStream_ >stream. For exec, the `stream` will also emit 'exit' when the process finishes. If the process finished normally, the process return value is passed to the 'exit' callback. If the process was interrupted by a signal, the following are passed to the 'exit' callback: null, < _string_ >signalName, < _boolean_ >didCoreDump, < _string_ >description.

@@ -392,0 +394,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc