first commit
This commit is contained in:
18
build/node_modules/ssh2/.travis.yml
generated
vendored
Normal file
18
build/node_modules/ssh2/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
sudo: false
|
||||
language: cpp
|
||||
notifications:
|
||||
email: false
|
||||
env:
|
||||
matrix:
|
||||
- TRAVIS_NODE_VERSION="0.10"
|
||||
- TRAVIS_NODE_VERSION="0.12"
|
||||
- TRAVIS_NODE_VERSION="4"
|
||||
- TRAVIS_NODE_VERSION="6"
|
||||
- TRAVIS_NODE_VERSION="7"
|
||||
install:
|
||||
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION
|
||||
- node --version
|
||||
- npm --version
|
||||
- npm install
|
||||
- ssh -V
|
||||
script: npm test
|
||||
19
build/node_modules/ssh2/LICENSE
generated
vendored
Normal file
19
build/node_modules/ssh2/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright Brian White. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
1053
build/node_modules/ssh2/README.md
generated
vendored
Normal file
1053
build/node_modules/ssh2/README.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
243
build/node_modules/ssh2/examples/server-chat.js
generated
vendored
Normal file
243
build/node_modules/ssh2/examples/server-chat.js
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
// **BEFORE RUNNING THIS SCRIPT:**
|
||||
// 1. The server portion is best run on non-Windows systems because they have
|
||||
// terminfo databases which are needed to properly work with different
|
||||
// terminal types of client connections
|
||||
// 2. Install `blessed`: `npm install blessed`
|
||||
// 3. Create a server host key in this same directory and name it `host.key`
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var blessed = require('blessed');
|
||||
var Server = require('ssh2').Server;
|
||||
|
||||
var RE_SPECIAL = /[\x00-\x1F\x7F]+|(?:\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K])/g;
|
||||
var MAX_MSG_LEN = 128;
|
||||
var MAX_NAME_LEN = 10;
|
||||
var PROMPT_NAME = 'Enter a nickname to use (max ' + MAX_NAME_LEN + ' chars): ';
|
||||
|
||||
var users = [];
|
||||
|
||||
function formatMessage(msg, output) {
|
||||
var output = output;
|
||||
output.parseTags = true;
|
||||
msg = output._parseTags(msg);
|
||||
output.parseTags = false;
|
||||
return msg;
|
||||
}
|
||||
|
||||
function userBroadcast(msg, source) {
|
||||
var sourceMsg = '> ' + msg;
|
||||
var name = '{cyan-fg}{bold}' + source.name + '{/}';
|
||||
msg = ': ' + msg;
|
||||
for (var i = 0; i < users.length; ++i) {
|
||||
var user = users[i];
|
||||
var output = user.output;
|
||||
if (source === user)
|
||||
output.add(sourceMsg);
|
||||
else
|
||||
output.add(formatMessage(name, output) + msg);
|
||||
}
|
||||
}
|
||||
|
||||
function localMessage(msg, source) {
|
||||
var output = source.output;
|
||||
output.add(formatMessage(msg, output));
|
||||
}
|
||||
|
||||
function noop(v) {}
|
||||
|
||||
new Server({
|
||||
hostKeys: [fs.readFileSync('host.key')],
|
||||
}, function(client) {
|
||||
var stream;
|
||||
var name;
|
||||
|
||||
client.on('authentication', function(ctx) {
|
||||
var nick = ctx.username;
|
||||
var prompt = PROMPT_NAME;
|
||||
var lowered;
|
||||
// Try to use username as nickname
|
||||
if (nick.length > 0 && nick.length <= MAX_NAME_LEN) {
|
||||
lowered = nick.toLowerCase();
|
||||
var ok = true;
|
||||
for (var i = 0; i < users.length; ++i) {
|
||||
if (users[i].name.toLowerCase() === lowered) {
|
||||
ok = false;
|
||||
prompt = 'That nickname is already in use.\n' + PROMPT_NAME;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
name = nick;
|
||||
return ctx.accept();
|
||||
}
|
||||
} else if (nick.length === 0)
|
||||
prompt = 'A nickname is required.\n' + PROMPT_NAME;
|
||||
else
|
||||
prompt = 'That nickname is too long.\n' + PROMPT_NAME;
|
||||
|
||||
if (ctx.method !== 'keyboard-interactive')
|
||||
return ctx.reject(['keyboard-interactive']);
|
||||
|
||||
ctx.prompt(prompt, function retryPrompt(answers) {
|
||||
if (answers.length === 0)
|
||||
return ctx.reject(['keyboard-interactive']);
|
||||
nick = answers[0];
|
||||
if (nick.length > MAX_NAME_LEN) {
|
||||
return ctx.prompt('That nickname is too long.\n' + PROMPT_NAME,
|
||||
retryPrompt);
|
||||
} else if (nick.length === 0) {
|
||||
return ctx.prompt('A nickname is required.\n' + PROMPT_NAME,
|
||||
retryPrompt);
|
||||
}
|
||||
lowered = nick.toLowerCase();
|
||||
for (var i = 0; i < users.length; ++i) {
|
||||
if (users[i].name.toLowerCase() === lowered) {
|
||||
return ctx.prompt('That nickname is already in use.\n' + PROMPT_NAME,
|
||||
retryPrompt);
|
||||
}
|
||||
}
|
||||
name = nick;
|
||||
ctx.accept();
|
||||
});
|
||||
}).on('ready', function() {
|
||||
var rows;
|
||||
var cols;
|
||||
var term;
|
||||
client.once('session', function(accept, reject) {
|
||||
accept().once('pty', function(accept, reject, info) {
|
||||
rows = info.rows;
|
||||
cols = info.cols;
|
||||
term = info.term;
|
||||
accept && accept();
|
||||
}).on('window-change', function(accept, reject, info) {
|
||||
rows = info.rows;
|
||||
cols = info.cols;
|
||||
if (stream) {
|
||||
stream.rows = rows;
|
||||
stream.columns = cols;
|
||||
stream.emit('resize');
|
||||
}
|
||||
accept && accept();
|
||||
}).once('shell', function(accept, reject) {
|
||||
stream = accept();
|
||||
users.push(stream);
|
||||
|
||||
stream.name = name;
|
||||
stream.rows = rows || 24;
|
||||
stream.columns = cols || 80;
|
||||
stream.isTTY = true;
|
||||
stream.setRawMode = noop;
|
||||
stream.on('error', noop);
|
||||
|
||||
var screen = new blessed.screen({
|
||||
autoPadding: true,
|
||||
smartCSR: true,
|
||||
program: new blessed.program({
|
||||
input: stream,
|
||||
output: stream
|
||||
}),
|
||||
terminal: term || 'ansi'
|
||||
});
|
||||
|
||||
screen.title = 'SSH Chatting as ' + name;
|
||||
// Disable local echo
|
||||
screen.program.attr('invisible', true);
|
||||
|
||||
var output = stream.output = new blessed.log({
|
||||
screen: screen,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
bottom: 2,
|
||||
scrollOnInput: true
|
||||
})
|
||||
screen.append(output);
|
||||
|
||||
screen.append(new blessed.box({
|
||||
screen: screen,
|
||||
height: 1,
|
||||
bottom: 1,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
type: 'line',
|
||||
ch: '='
|
||||
}));
|
||||
|
||||
var input = new blessed.textbox({
|
||||
screen: screen,
|
||||
bottom: 0,
|
||||
height: 1,
|
||||
width: '100%',
|
||||
inputOnFocus: true
|
||||
});
|
||||
screen.append(input);
|
||||
|
||||
input.focus();
|
||||
|
||||
// Local greetings
|
||||
localMessage('{blue-bg}{white-fg}{bold}Welcome to SSH Chat!{/}\n'
|
||||
+ 'There are {bold}'
|
||||
+ (users.length - 1)
|
||||
+ '{/} other user(s) connected.\n'
|
||||
+ 'Type /quit or /exit to exit the chat.',
|
||||
stream);
|
||||
|
||||
// Let everyone else know that this user just joined
|
||||
for (var i = 0; i < users.length; ++i) {
|
||||
var user = users[i];
|
||||
var output = user.output;
|
||||
if (user === stream)
|
||||
continue;
|
||||
output.add(formatMessage('{green-fg}*** {bold}', output)
|
||||
+ name
|
||||
+ formatMessage('{/bold} has joined the chat{/}', output));
|
||||
}
|
||||
|
||||
screen.render();
|
||||
// XXX This fake resize event is needed for some terminals in order to
|
||||
// have everything display correctly
|
||||
screen.program.emit('resize');
|
||||
|
||||
// Read a line of input from the user
|
||||
input.on('submit', function(line) {
|
||||
input.clearValue();
|
||||
screen.render();
|
||||
if (!input.focused)
|
||||
input.focus();
|
||||
line = line.replace(RE_SPECIAL, '').trim();
|
||||
if (line.length > MAX_MSG_LEN)
|
||||
line = line.substring(0, MAX_MSG_LEN);
|
||||
if (line.length > 0) {
|
||||
if (line === '/quit' || line === '/exit')
|
||||
stream.end();
|
||||
else
|
||||
userBroadcast(line, stream);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}).on('end', function() {
|
||||
if (stream !== undefined) {
|
||||
spliceOne(users, users.indexOf(stream));
|
||||
// Let everyone else know that this user just left
|
||||
for (var i = 0; i < users.length; ++i) {
|
||||
var user = users[i];
|
||||
var output = user.output;
|
||||
output.add(formatMessage('{magenta-fg}*** {bold}', output)
|
||||
+ name
|
||||
+ formatMessage('{/bold} has left the chat{/}', output));
|
||||
}
|
||||
}
|
||||
}).on('error', function(err) {
|
||||
// Ignore errors
|
||||
});
|
||||
}).listen(0, function() {
|
||||
console.log('Listening on port ' + this.address().port);
|
||||
});
|
||||
|
||||
function spliceOne(list, index) {
|
||||
for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
|
||||
list[i] = list[k];
|
||||
list.pop();
|
||||
}
|
||||
96
build/node_modules/ssh2/examples/sftp-server-download-only.js
generated
vendored
Normal file
96
build/node_modules/ssh2/examples/sftp-server-download-only.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
var constants = require('constants');
|
||||
var fs = require('fs');
|
||||
|
||||
var ssh2 = require('ssh2');
|
||||
var OPEN_MODE = ssh2.SFTP_OPEN_MODE;
|
||||
var STATUS_CODE = ssh2.SFTP_STATUS_CODE;
|
||||
|
||||
new ssh2.Server({
|
||||
hostKeys: [fs.readFileSync('host.key')]
|
||||
}, function(client) {
|
||||
console.log('Client connected!');
|
||||
|
||||
client.on('authentication', function(ctx) {
|
||||
if (ctx.method === 'password'
|
||||
&& ctx.username === 'foo'
|
||||
&& ctx.password === 'bar')
|
||||
ctx.accept();
|
||||
else
|
||||
ctx.reject(['password']);
|
||||
}).on('ready', function() {
|
||||
console.log('Client authenticated!');
|
||||
|
||||
client.on('session', function(accept, reject) {
|
||||
var session = accept();
|
||||
session.on('sftp', function(accept, reject) {
|
||||
console.log('Client SFTP session');
|
||||
var openFiles = {};
|
||||
var handleCount = 0;
|
||||
// `sftpStream` is an `SFTPStream` instance in server mode
|
||||
// see: https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md
|
||||
var sftpStream = accept();
|
||||
sftpStream.on('OPEN', function(reqid, filename, flags, attrs) {
|
||||
console.log('OPEN', filename);
|
||||
// only allow opening /tmp/foo.txt for writing
|
||||
if (filename !== '/tmp/foo.txt' || !(flags & OPEN_MODE.READ))
|
||||
return sftpStream.status(reqid, STATUS_CODE.FAILURE);
|
||||
// create a fake handle to return to the client, this could easily
|
||||
// be a real file descriptor number for example if actually opening
|
||||
// the file on the disk
|
||||
var handle = new Buffer(4);
|
||||
openFiles[handleCount] = { read: false };
|
||||
handle.writeUInt32BE(handleCount++, 0, true);
|
||||
sftpStream.handle(reqid, handle);
|
||||
console.log('Opening file for read')
|
||||
}).on('READ', function(reqid, handle, offset, length) {
|
||||
if (handle.length !== 4 || !openFiles[handle.readUInt32BE(0, true)])
|
||||
return sftpStream.status(reqid, STATUS_CODE.FAILURE);
|
||||
// fake the read
|
||||
var state = openFiles[handle.readUInt32BE(0, true)];
|
||||
if (state.read)
|
||||
sftpStream.status(reqid, STATUS_CODE.EOF);
|
||||
else {
|
||||
state.read = true;
|
||||
sftpStream.data(reqid, 'bar');
|
||||
console.log('Read from file at offset %d, length %d', offset, length);
|
||||
}
|
||||
}).on('CLOSE', function(reqid, handle) {
|
||||
var fnum;
|
||||
if (handle.length !== 4 || !openFiles[(fnum = handle.readUInt32BE(0, true))])
|
||||
return sftpStream.status(reqid, STATUS_CODE.FAILURE);
|
||||
delete openFiles[fnum];
|
||||
sftpStream.status(reqid, STATUS_CODE.OK);
|
||||
console.log('Closing file');
|
||||
}).on('REALPATH', function(reqid, path) {
|
||||
var name = [{
|
||||
filename: '/tmp/foo.txt',
|
||||
longname: '-rwxrwxrwx 1 foo foo 3 Dec 8 2009 foo.txt',
|
||||
attrs: {}
|
||||
}];
|
||||
sftpStream.name(reqid, name);
|
||||
}).on('STAT', onSTAT)
|
||||
.on('LSTAT', onSTAT);
|
||||
function onSTAT(reqid, path) {
|
||||
if (path !== '/tmp/foo.txt')
|
||||
return sftpStream.status(reqid, STATUS_CODE.FAILURE);
|
||||
var mode = constants.S_IFREG; // Regular file
|
||||
mode |= constants.S_IRWXU; // read, write, execute for user
|
||||
mode |= constants.S_IRWXG; // read, write, execute for group
|
||||
mode |= constants.S_IRWXO; // read, write, execute for other
|
||||
sftpStream.attrs(reqid, {
|
||||
mode: mode,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
size: 3,
|
||||
atime: Date.now(),
|
||||
mtime: Date.now()
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}).on('end', function() {
|
||||
console.log('Client disconnected');
|
||||
});
|
||||
}).listen(0, '127.0.0.1', function() {
|
||||
console.log('Listening on port ' + this.address().port);
|
||||
});
|
||||
506
build/node_modules/ssh2/lib/Channel.js
generated
vendored
Normal file
506
build/node_modules/ssh2/lib/Channel.js
generated
vendored
Normal file
@@ -0,0 +1,506 @@
|
||||
var inherits = require('util').inherits;
|
||||
var DuplexStream = require('stream').Duplex;
|
||||
var ReadableStream = require('stream').Readable;
|
||||
var WritableStream = require('stream').Writable;
|
||||
|
||||
var STDERR = require('ssh2-streams').constants.CHANNEL_EXTENDED_DATATYPE.STDERR;
|
||||
|
||||
var PACKET_SIZE = 32 * 1024;
|
||||
var MAX_WINDOW = 1 * 1024 * 1024;
|
||||
var WINDOW_THRESHOLD = MAX_WINDOW / 2;
|
||||
var CUSTOM_EVENTS = [
|
||||
'CHANNEL_EOF',
|
||||
'CHANNEL_CLOSE',
|
||||
'CHANNEL_DATA',
|
||||
'CHANNEL_EXTENDED_DATA',
|
||||
'CHANNEL_WINDOW_ADJUST',
|
||||
'CHANNEL_SUCCESS',
|
||||
'CHANNEL_FAILURE',
|
||||
'CHANNEL_REQUEST'
|
||||
];
|
||||
var CUSTOM_EVENTS_LEN = CUSTOM_EVENTS.length;
|
||||
|
||||
function Channel(info, client, opts) {
|
||||
var streamOpts = {
|
||||
highWaterMark: MAX_WINDOW,
|
||||
allowHalfOpen: (!opts || (opts && opts.allowHalfOpen !== false))
|
||||
};
|
||||
|
||||
this.allowHalfOpen = streamOpts.allowHalfOpen;
|
||||
|
||||
DuplexStream.call(this, streamOpts);
|
||||
|
||||
var self = this;
|
||||
var server = opts && opts.server;
|
||||
|
||||
this.server = server;
|
||||
this.type = info.type;
|
||||
this.subtype = undefined;
|
||||
/*
|
||||
incoming and outgoing contain these properties:
|
||||
{
|
||||
id: undefined,
|
||||
window: undefined,
|
||||
packetSize: undefined,
|
||||
state: 'closed'
|
||||
}
|
||||
*/
|
||||
var incoming = this.incoming = info.incoming;
|
||||
var incomingId = incoming.id;
|
||||
var outgoing = this.outgoing = info.outgoing;
|
||||
var callbacks = this._callbacks = [];
|
||||
var exitCode;
|
||||
var exitSignal;
|
||||
var exitDump;
|
||||
var exitDesc;
|
||||
var exitLang;
|
||||
|
||||
this._client = client;
|
||||
this._hasX11 = false;
|
||||
|
||||
var channels = client._channels;
|
||||
var sshstream = client._sshstream;
|
||||
|
||||
function ondrain() {
|
||||
if (self._waitClientDrain) {
|
||||
self._waitClientDrain = false;
|
||||
if (!self._waitWindow) {
|
||||
if (self._chunk)
|
||||
self._write(self._chunk, null, self._chunkcb);
|
||||
else if (self._chunkcb)
|
||||
self._chunkcb();
|
||||
else if (self._chunkErr)
|
||||
self.stderr._write(self._chunkErr, null, self._chunkcbErr);
|
||||
else if (self._chunkcbErr)
|
||||
self._chunkcbErr();
|
||||
}
|
||||
}
|
||||
}
|
||||
client._sock.on('drain', ondrain);
|
||||
|
||||
sshstream.once('CHANNEL_EOF:' + incomingId, function() {
|
||||
if (incoming.state === 'closed' || incoming.state === 'eof')
|
||||
return;
|
||||
incoming.state = 'eof';
|
||||
|
||||
if (self.readable)
|
||||
self.push(null);
|
||||
if (!server && self.stderr.readable)
|
||||
self.stderr.push(null);
|
||||
}).once('CHANNEL_CLOSE:' + incomingId, function() {
|
||||
if (incoming.state === 'closed')
|
||||
return;
|
||||
incoming.state = 'closed';
|
||||
|
||||
if (self.readable)
|
||||
self.push(null);
|
||||
if (server && self.stderr.writable)
|
||||
self.stderr.end();
|
||||
else if (!server && self.stderr.readable)
|
||||
self.stderr.push(null);
|
||||
|
||||
if (outgoing.state === 'open' || outgoing.state === 'eof')
|
||||
self.close();
|
||||
if (outgoing.state === 'closing')
|
||||
outgoing.state = 'closed';
|
||||
|
||||
delete channels[incomingId];
|
||||
|
||||
var state = self._writableState;
|
||||
client._sock.removeListener('drain', ondrain);
|
||||
if (!state.ending && !state.finished)
|
||||
self.end();
|
||||
|
||||
// Take care of any outstanding channel requests
|
||||
self._callbacks = [];
|
||||
for (var i = 0; i < callbacks.length; ++i)
|
||||
callbacks[i](true);
|
||||
callbacks = self._callbacks;
|
||||
|
||||
if (!server) {
|
||||
// align more with node child processes, where the close event gets the
|
||||
// same arguments as the exit event
|
||||
if (!self.readable) {
|
||||
if (exitCode === null) {
|
||||
self.emit('close', exitCode, exitSignal, exitDump, exitDesc,
|
||||
exitLang);
|
||||
} else
|
||||
self.emit('close', exitCode);
|
||||
} else {
|
||||
self.once('end', function() {
|
||||
if (exitCode === null) {
|
||||
self.emit('close', exitCode, exitSignal, exitDump, exitDesc,
|
||||
exitLang);
|
||||
} else
|
||||
self.emit('close', exitCode);
|
||||
});
|
||||
}
|
||||
|
||||
if (!self.stderr.readable)
|
||||
self.stderr.emit('close');
|
||||
else {
|
||||
self.stderr.once('end', function() {
|
||||
self.stderr.emit('close');
|
||||
});
|
||||
}
|
||||
} else { // Server mode
|
||||
if (!self.readable)
|
||||
self.emit('close');
|
||||
else {
|
||||
self.once('end', function() {
|
||||
self.emit('close');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < CUSTOM_EVENTS_LEN; ++i)
|
||||
sshstream.removeAllListeners(CUSTOM_EVENTS[i] + ':' + incomingId);
|
||||
}).on('CHANNEL_DATA:' + incomingId, function(data) {
|
||||
// the remote party should not be sending us data if there is no window
|
||||
// space available ...
|
||||
if (incoming.window === 0)
|
||||
return;
|
||||
|
||||
incoming.window -= data.length;
|
||||
|
||||
if (!self.push(data)) {
|
||||
self._waitChanDrain = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (incoming.window <= WINDOW_THRESHOLD)
|
||||
windowAdjust(self);
|
||||
}).on('CHANNEL_WINDOW_ADJUST:' + incomingId, function(amt) {
|
||||
// the server is allowing us to send `amt` more bytes of data
|
||||
outgoing.window += amt;
|
||||
|
||||
if (self._waitWindow) {
|
||||
self._waitWindow = false;
|
||||
if (!self._waitClientDrain) {
|
||||
if (self._chunk)
|
||||
self._write(self._chunk, null, self._chunkcb);
|
||||
else if (self._chunkcb)
|
||||
self._chunkcb();
|
||||
else if (self._chunkErr)
|
||||
self.stderr._write(self._chunkErr, null, self._chunkcbErr);
|
||||
else if (self._chunkcbErr)
|
||||
self._chunkcbErr();
|
||||
}
|
||||
}
|
||||
}).on('CHANNEL_SUCCESS:' + incomingId, function() {
|
||||
if (server) {
|
||||
sshstream._kalast = Date.now();
|
||||
sshstream._kacnt = 0;
|
||||
} else
|
||||
client._resetKA();
|
||||
if (callbacks.length)
|
||||
callbacks.shift()(false);
|
||||
}).on('CHANNEL_FAILURE:' + incomingId, function() {
|
||||
if (server) {
|
||||
sshstream._kalast = Date.now();
|
||||
sshstream._kacnt = 0;
|
||||
} else
|
||||
client._resetKA();
|
||||
if (callbacks.length)
|
||||
callbacks.shift()(true);
|
||||
}).on('CHANNEL_REQUEST:' + incomingId, function(info) {
|
||||
if (!server) {
|
||||
if (info.request === 'exit-status') {
|
||||
self.emit('exit', exitCode = info.code);
|
||||
return;
|
||||
} else if (info.request === 'exit-signal') {
|
||||
self.emit('exit',
|
||||
exitCode = null,
|
||||
exitSignal = 'SIG' + info.signal,
|
||||
exitDump = info.coredump,
|
||||
exitDesc = info.description,
|
||||
exitLang = info.lang);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// keepalive request? OpenSSH will send one as a channel request if there
|
||||
// is a channel open
|
||||
|
||||
if (info.wantReply)
|
||||
sshstream.channelFailure(outgoing.id);
|
||||
});
|
||||
|
||||
this.stdin = this.stdout = this;
|
||||
|
||||
if (server)
|
||||
this.stderr = new ServerStderr(this);
|
||||
else {
|
||||
this.stderr = new ReadableStream(streamOpts);
|
||||
this.stderr._read = function(n) {
|
||||
if (self._waitChanDrain) {
|
||||
self._waitChanDrain = false;
|
||||
if (incoming.window <= WINDOW_THRESHOLD)
|
||||
windowAdjust(self);
|
||||
}
|
||||
};
|
||||
|
||||
sshstream.on('CHANNEL_EXTENDED_DATA:' + incomingId,
|
||||
function(type, data) {
|
||||
// the remote party should not be sending us data if there is no window
|
||||
// space available ...
|
||||
if (incoming.window === 0)
|
||||
return;
|
||||
|
||||
incoming.window -= data.length;
|
||||
|
||||
if (!self.stderr.push(data)) {
|
||||
self._waitChanDrain = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (incoming.window <= WINDOW_THRESHOLD)
|
||||
windowAdjust(self);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// outgoing data
|
||||
this._waitClientDrain = false; // Client stream-level backpressure
|
||||
this._waitWindow = false; // SSH-level backpressure
|
||||
|
||||
// incoming data
|
||||
this._waitChanDrain = false; // Channel Readable side backpressure
|
||||
|
||||
this._chunk = undefined;
|
||||
this._chunkcb = undefined;
|
||||
this._chunkErr = undefined;
|
||||
this._chunkcbErr = undefined;
|
||||
|
||||
function onFinish() {
|
||||
self.eof();
|
||||
if (server || (!server && !self.allowHalfOpen))
|
||||
self.close();
|
||||
self.writable = false;
|
||||
}
|
||||
this.on('finish', onFinish)
|
||||
.on('prefinish', onFinish); // for node v0.11+
|
||||
function onEnd() {
|
||||
self.readable = false;
|
||||
}
|
||||
this.on('end', onEnd)
|
||||
.on('close', onEnd);
|
||||
}
|
||||
inherits(Channel, DuplexStream);
|
||||
|
||||
Channel.prototype.eof = function() {
|
||||
var ret = true;
|
||||
var outgoing = this.outgoing;
|
||||
|
||||
if (outgoing.state === 'open') {
|
||||
outgoing.state = 'eof';
|
||||
ret = this._client._sshstream.channelEOF(outgoing.id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
Channel.prototype.close = function() {
|
||||
var ret = true;
|
||||
var outgoing = this.outgoing;
|
||||
|
||||
if (outgoing.state === 'open' || outgoing.state === 'eof') {
|
||||
outgoing.state = 'closing';
|
||||
ret = this._client._sshstream.channelClose(outgoing.id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
Channel.prototype._read = function(n) {
|
||||
if (this._waitChanDrain) {
|
||||
this._waitChanDrain = false;
|
||||
if (this.incoming.window <= WINDOW_THRESHOLD)
|
||||
windowAdjust(this);
|
||||
}
|
||||
};
|
||||
|
||||
Channel.prototype._write = function(data, encoding, cb) {
|
||||
var sshstream = this._client._sshstream;
|
||||
var outgoing = this.outgoing;
|
||||
var packetSize = outgoing.packetSize;
|
||||
var id = outgoing.id;
|
||||
var window = outgoing.window;
|
||||
var len = data.length;
|
||||
var p = 0;
|
||||
var ret;
|
||||
var buf;
|
||||
var sliceLen;
|
||||
|
||||
if (outgoing.state !== 'open')
|
||||
return;
|
||||
|
||||
while (len - p > 0 && window > 0) {
|
||||
sliceLen = len - p;
|
||||
if (sliceLen > window)
|
||||
sliceLen = window;
|
||||
if (sliceLen > packetSize)
|
||||
sliceLen = packetSize;
|
||||
|
||||
ret = sshstream.channelData(id, data.slice(p, p + sliceLen));
|
||||
|
||||
p += sliceLen;
|
||||
window -= sliceLen;
|
||||
|
||||
if (!ret) {
|
||||
this._waitClientDrain = true;
|
||||
this._chunk = undefined;
|
||||
this._chunkcb = cb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
outgoing.window = window;
|
||||
|
||||
if (len - p > 0) {
|
||||
if (window === 0)
|
||||
this._waitWindow = true;
|
||||
if (p > 0) {
|
||||
// partial
|
||||
buf = new Buffer(len - p);
|
||||
data.copy(buf, 0, p);
|
||||
this._chunk = buf;
|
||||
} else
|
||||
this._chunk = data;
|
||||
this._chunkcb = cb;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._waitClientDrain)
|
||||
cb();
|
||||
};
|
||||
|
||||
Channel.prototype.destroy = function() {
|
||||
this.end();
|
||||
};
|
||||
|
||||
// session type-specific methods
|
||||
Channel.prototype.setWindow = function(rows, cols, height, width) {
|
||||
if (this.server)
|
||||
throw new Error('Client-only method called in server mode');
|
||||
|
||||
if (this.type === 'session'
|
||||
&& (this.subtype === 'shell' || this.subtype === 'exec')
|
||||
&& this.writable
|
||||
&& this.outgoing.state === 'open') {
|
||||
return this._client._sshstream.windowChange(this.outgoing.id,
|
||||
rows,
|
||||
cols,
|
||||
height,
|
||||
width);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
Channel.prototype.signal = function(signalName) {
|
||||
if (this.server)
|
||||
throw new Error('Client-only method called in server mode');
|
||||
|
||||
if (this.type === 'session'
|
||||
&& this.writable
|
||||
&& this.outgoing.state === 'open')
|
||||
return this._client._sshstream.signal(this.outgoing.id, signalName);
|
||||
|
||||
return true;
|
||||
};
|
||||
Channel.prototype.exit = function(name, coreDumped, msg) {
|
||||
if (!this.server)
|
||||
throw new Error('Server-only method called in client mode');
|
||||
|
||||
if (this.type === 'session'
|
||||
&& this.writable
|
||||
&& this.outgoing.state === 'open') {
|
||||
if (typeof name === 'number')
|
||||
return this._client._sshstream.exitStatus(this.outgoing.id, name);
|
||||
else {
|
||||
return this._client._sshstream.exitSignal(this.outgoing.id,
|
||||
name,
|
||||
coreDumped,
|
||||
msg);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Channel.MAX_WINDOW = MAX_WINDOW;
|
||||
Channel.PACKET_SIZE = PACKET_SIZE;
|
||||
|
||||
function windowAdjust(self) {
|
||||
if (self.outgoing.state !== 'open')
|
||||
return true;
|
||||
var amt = MAX_WINDOW - self.incoming.window;
|
||||
if (amt <= 0)
|
||||
return true;
|
||||
self.incoming.window += amt;
|
||||
return self._client._sshstream.channelWindowAdjust(self.outgoing.id, amt);
|
||||
}
|
||||
|
||||
function ServerStderr(channel) {
|
||||
WritableStream.call(this, { highWaterMark: MAX_WINDOW });
|
||||
this._channel = channel;
|
||||
}
|
||||
inherits(ServerStderr, WritableStream);
|
||||
|
||||
ServerStderr.prototype._write = function(data, encoding, cb) {
|
||||
var channel = this._channel;
|
||||
var sshstream = channel._client._sshstream;
|
||||
var outgoing = channel.outgoing;
|
||||
var packetSize = outgoing.packetSize;
|
||||
var id = outgoing.id;
|
||||
var window = outgoing.window;
|
||||
var len = data.length;
|
||||
var p = 0;
|
||||
var ret;
|
||||
var buf;
|
||||
var sliceLen;
|
||||
|
||||
if (channel.outgoing.state !== 'open')
|
||||
return;
|
||||
|
||||
while (len - p > 0 && window > 0) {
|
||||
sliceLen = len - p;
|
||||
if (sliceLen > window)
|
||||
sliceLen = window;
|
||||
if (sliceLen > packetSize)
|
||||
sliceLen = packetSize;
|
||||
|
||||
ret = sshstream.channelExtData(id, data.slice(p, p + sliceLen), STDERR);
|
||||
|
||||
p += sliceLen;
|
||||
window -= sliceLen;
|
||||
|
||||
if (!ret) {
|
||||
channel._waitClientDrain = true;
|
||||
channel._chunkErr = undefined;
|
||||
channel._chunkcbErr = cb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
outgoing.window = window;
|
||||
|
||||
if (len - p > 0) {
|
||||
if (window === 0)
|
||||
channel._waitWindow = true;
|
||||
if (p > 0) {
|
||||
// partial
|
||||
buf = new Buffer(len - p);
|
||||
data.copy(buf, 0, p);
|
||||
channel._chunkErr = buf;
|
||||
} else
|
||||
channel._chunkErr = data;
|
||||
channel._chunkcbErr = cb;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!channel._waitClientDrain)
|
||||
cb();
|
||||
};
|
||||
|
||||
module.exports = Channel;
|
||||
145
build/node_modules/ssh2/lib/SFTPWrapper.js
generated
vendored
Normal file
145
build/node_modules/ssh2/lib/SFTPWrapper.js
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
// This wrapper class is used to retain backwards compatibility with
|
||||
// pre-v0.4 ssh2. If it weren't for `read()` and `write()` being used by the
|
||||
// streams2/3 API, we could just pass the SFTPStream directly to the end user...
|
||||
|
||||
var inherits = require('util').inherits,
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
|
||||
function SFTPWrapper(stream) {
|
||||
var self = this;
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
this._stream = stream;
|
||||
|
||||
stream.on('error', function(err) {
|
||||
self.emit('error', err);
|
||||
}).on('end', function() {
|
||||
self.emit('end');
|
||||
}).on('close', function() {
|
||||
self.emit('close');
|
||||
}).on('continue', function() {
|
||||
self.emit('continue');
|
||||
});
|
||||
}
|
||||
inherits(SFTPWrapper, EventEmitter);
|
||||
|
||||
// stream-related methods to pass on
|
||||
SFTPWrapper.prototype.end = function() {
|
||||
return this._stream.end();
|
||||
};
|
||||
// SFTPStream client methods
|
||||
SFTPWrapper.prototype.createReadStream = function(path, options) {
|
||||
return this._stream.createReadStream(path, options);
|
||||
};
|
||||
SFTPWrapper.prototype.createWriteStream = function(path, options) {
|
||||
return this._stream.createWriteStream(path, options);
|
||||
};
|
||||
SFTPWrapper.prototype.open = function(path, flags, attrs, cb) {
|
||||
return this._stream.open(path, flags, attrs, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.close = function(handle, cb) {
|
||||
return this._stream.close(handle, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.read = function(handle, buf, off, len, position, cb) {
|
||||
return this._stream.readData(handle, buf, off, len, position, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.write = function(handle, buf, off, len, position, cb) {
|
||||
return this._stream.writeData(handle, buf, off, len, position, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.fastGet = function(remotePath, localPath, opts, cb) {
|
||||
return this._stream.fastGet(remotePath, localPath, opts, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.fastPut = function(localPath, remotePath, opts, cb) {
|
||||
return this._stream.fastPut(localPath, remotePath, opts, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.readFile = function(path, options, callback_) {
|
||||
return this._stream.readFile(path, options, callback_);
|
||||
};
|
||||
SFTPWrapper.prototype.writeFile = function(path, data, options, callback_) {
|
||||
return this._stream.writeFile(path, data, options, callback_);
|
||||
};
|
||||
SFTPWrapper.prototype.appendFile = function(path, data, options, callback_) {
|
||||
return this._stream.appendFile(path, data, options, callback_);
|
||||
};
|
||||
SFTPWrapper.prototype.exists = function(path, cb) {
|
||||
return this._stream.exists(path, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.unlink = function(filename, cb) {
|
||||
return this._stream.unlink(filename, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.rename = function(oldPath, newPath, cb) {
|
||||
return this._stream.rename(oldPath, newPath, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.mkdir = function(path, attrs, cb) {
|
||||
return this._stream.mkdir(path, attrs, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.rmdir = function(path, cb) {
|
||||
return this._stream.rmdir(path, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.readdir = function(where, opts, cb) {
|
||||
return this._stream.readdir(where, opts, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.fstat = function(handle, cb) {
|
||||
return this._stream.fstat(handle, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.stat = function(path, cb) {
|
||||
return this._stream.stat(path, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.lstat = function(path, cb) {
|
||||
return this._stream.lstat(path, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.opendir = function(path, cb) {
|
||||
return this._stream.opendir(path, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.setstat = function(path, attrs, cb) {
|
||||
return this._stream.setstat(path, attrs, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.fsetstat = function(handle, attrs, cb) {
|
||||
return this._stream.fsetstat(handle, attrs, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.futimes = function(handle, atime, mtime, cb) {
|
||||
return this._stream.futimes(handle, atime, mtime, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.utimes = function(path, atime, mtime, cb) {
|
||||
return this._stream.utimes(path, atime, mtime, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.fchown = function(handle, uid, gid, cb) {
|
||||
return this._stream.fchown(handle, uid, gid, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.chown = function(path, uid, gid, cb) {
|
||||
return this._stream.chown(path, uid, gid, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.fchmod = function(handle, mode, cb) {
|
||||
return this._stream.fchmod(handle, mode, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.chmod = function(path, mode, cb) {
|
||||
return this._stream.chmod(path, mode, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.readlink = function(path, cb) {
|
||||
return this._stream.readlink(path, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.symlink = function(targetPath, linkPath, cb) {
|
||||
return this._stream.symlink(targetPath, linkPath, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.realpath = function(path, cb) {
|
||||
return this._stream.realpath(path, cb);
|
||||
};
|
||||
// extended requests
|
||||
SFTPWrapper.prototype.ext_openssh_rename = function(oldPath, newPath, cb) {
|
||||
return this._stream.ext_openssh_rename(oldPath, newPath, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.ext_openssh_statvfs = function(path, cb) {
|
||||
return this._stream.ext_openssh_statvfs(path, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.ext_openssh_fstatvfs = function(handle, cb) {
|
||||
return this._stream.ext_openssh_fstatvfs(handle, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.ext_openssh_hardlink = function(oldPath, newPath, cb) {
|
||||
return this._stream.ext_openssh_hardlink(oldPath, newPath, cb);
|
||||
};
|
||||
SFTPWrapper.prototype.ext_openssh_fsync = function(handle, cb) {
|
||||
return this._stream.ext_openssh_fsync(handle, cb);
|
||||
};
|
||||
|
||||
module.exports = SFTPWrapper;
|
||||
412
build/node_modules/ssh2/lib/agent.js
generated
vendored
Normal file
412
build/node_modules/ssh2/lib/agent.js
generated
vendored
Normal file
@@ -0,0 +1,412 @@
|
||||
var Socket = require('net').Socket;
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var inherits = require('util').inherits;
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var cp = require('child_process');
|
||||
|
||||
var REQUEST_IDENTITIES = 11;
|
||||
var IDENTITIES_ANSWER = 12;
|
||||
var SIGN_REQUEST = 13;
|
||||
var SIGN_RESPONSE = 14;
|
||||
var FAILURE = 5;
|
||||
|
||||
var RE_CYGWIN_SOCK = /^\!<socket >(\d+) s ([A-Z0-9]{8}\-[A-Z0-9]{8}\-[A-Z0-9]{8}\-[A-Z0-9]{8})/;
|
||||
|
||||
module.exports = function(sockPath, key, keyType, data, cb) {
|
||||
var sock;
|
||||
var error;
|
||||
var sig;
|
||||
var datalen;
|
||||
var keylen = 0;
|
||||
var isSigning = Buffer.isBuffer(key);
|
||||
var type;
|
||||
var count = 0;
|
||||
var siglen = 0;
|
||||
var nkeys = 0;
|
||||
var keys;
|
||||
var comlen = 0;
|
||||
var comment = false;
|
||||
var accept;
|
||||
var reject;
|
||||
|
||||
if (typeof key === 'function' && typeof keyType === 'function') {
|
||||
// agent forwarding
|
||||
accept = key;
|
||||
reject = keyType;
|
||||
} else if (isSigning) {
|
||||
keylen = key.length;
|
||||
datalen = data.length;
|
||||
} else {
|
||||
cb = key;
|
||||
key = undefined;
|
||||
}
|
||||
|
||||
function onconnect() {
|
||||
var buf;
|
||||
if (isSigning) {
|
||||
/*
|
||||
byte SSH2_AGENTC_SIGN_REQUEST
|
||||
string key_blob
|
||||
string data
|
||||
uint32 flags
|
||||
*/
|
||||
var p = 9;
|
||||
buf = new Buffer(4 + 1 + 4 + keylen + 4 + datalen + 4);
|
||||
buf.writeUInt32BE(buf.length - 4, 0, true);
|
||||
buf[4] = SIGN_REQUEST;
|
||||
buf.writeUInt32BE(keylen, 5, true);
|
||||
key.copy(buf, p);
|
||||
buf.writeUInt32BE(datalen, p += keylen, true);
|
||||
data.copy(buf, p += 4);
|
||||
buf.writeUInt32BE(0, p += datalen, true);
|
||||
sock.write(buf);
|
||||
} else {
|
||||
/*
|
||||
byte SSH2_AGENTC_REQUEST_IDENTITIES
|
||||
*/
|
||||
sock.write(new Buffer([0, 0, 0, 1, REQUEST_IDENTITIES]));
|
||||
}
|
||||
}
|
||||
function ondata(chunk) {
|
||||
for (var i = 0, len = chunk.length; i < len; ++i) {
|
||||
if (type === undefined) {
|
||||
// skip over packet length
|
||||
if (++count === 5) {
|
||||
type = chunk[i];
|
||||
count = 0;
|
||||
}
|
||||
} else if (type === SIGN_RESPONSE) {
|
||||
/*
|
||||
byte SSH2_AGENT_SIGN_RESPONSE
|
||||
string signature_blob
|
||||
*/
|
||||
if (!sig) {
|
||||
siglen <<= 8;
|
||||
siglen += chunk[i];
|
||||
if (++count === 4) {
|
||||
sig = new Buffer(siglen);
|
||||
count = 0;
|
||||
}
|
||||
} else {
|
||||
sig[count] = chunk[i];
|
||||
if (++count === siglen) {
|
||||
sock.removeAllListeners('data');
|
||||
return sock.destroy();
|
||||
}
|
||||
}
|
||||
} else if (type === IDENTITIES_ANSWER) {
|
||||
/*
|
||||
byte SSH2_AGENT_IDENTITIES_ANSWER
|
||||
uint32 num_keys
|
||||
|
||||
Followed by zero or more consecutive keys, encoded as:
|
||||
|
||||
string public key blob
|
||||
string public key comment
|
||||
*/
|
||||
if (keys === undefined) {
|
||||
nkeys <<= 8;
|
||||
nkeys += chunk[i];
|
||||
if (++count === 4) {
|
||||
keys = new Array(nkeys);
|
||||
count = 0;
|
||||
if (nkeys === 0) {
|
||||
sock.removeAllListeners('data');
|
||||
return sock.destroy();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!key) {
|
||||
keylen <<= 8;
|
||||
keylen += chunk[i];
|
||||
if (++count === 4) {
|
||||
key = new Buffer(keylen);
|
||||
count = 0;
|
||||
}
|
||||
} else if (comment === false) {
|
||||
key[count] = chunk[i];
|
||||
if (++count === keylen) {
|
||||
keys[nkeys - 1] = key;
|
||||
keylen = 0;
|
||||
count = 0;
|
||||
comment = true;
|
||||
if (--nkeys === 0) {
|
||||
key = undefined;
|
||||
sock.removeAllListeners('data');
|
||||
return sock.destroy();
|
||||
}
|
||||
}
|
||||
} else if (comment === true) {
|
||||
comlen <<= 8;
|
||||
comlen += chunk[i];
|
||||
if (++count === 4) {
|
||||
count = 0;
|
||||
if (comlen > 0)
|
||||
comment = comlen;
|
||||
else {
|
||||
key = undefined;
|
||||
comment = false;
|
||||
}
|
||||
comlen = 0;
|
||||
}
|
||||
} else {
|
||||
// skip comments
|
||||
if (++count === comment) {
|
||||
comment = false;
|
||||
count = 0;
|
||||
key = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (type === FAILURE) {
|
||||
if (isSigning)
|
||||
error = new Error('Agent unable to sign data');
|
||||
else
|
||||
error = new Error('Unable to retrieve list of keys from agent');
|
||||
sock.removeAllListeners('data');
|
||||
return sock.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
function onerror(err) {
|
||||
error = err;
|
||||
}
|
||||
function onclose() {
|
||||
if (error)
|
||||
cb(error);
|
||||
else if ((isSigning && !sig) || (!isSigning && !keys))
|
||||
cb(new Error('Unexpected disconnection from agent'));
|
||||
else if (isSigning && sig)
|
||||
cb(undefined, sig);
|
||||
else if (!isSigning && keys)
|
||||
cb(undefined, keys);
|
||||
}
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
if (sockPath === 'pageant') {
|
||||
// Pageant (PuTTY authentication agent)
|
||||
sock = new PageantSock();
|
||||
} else {
|
||||
// cygwin ssh-agent instance
|
||||
var triedCygpath = false;
|
||||
fs.readFile(sockPath, function readCygsocket(err, data) {
|
||||
if (err) {
|
||||
if (triedCygpath)
|
||||
return cb(new Error('Invalid cygwin unix socket path'));
|
||||
// try using `cygpath` to convert a possible *nix-style path to the
|
||||
// real Windows path before giving up ...
|
||||
cp.exec('cygpath -w "' + sockPath + '"',
|
||||
function(err, stdout, stderr) {
|
||||
if (err || stdout.length === 0)
|
||||
return cb(new Error('Invalid cygwin unix socket path'));
|
||||
triedCygpath = true;
|
||||
sockPath = stdout.toString().replace(/[\r\n]/g, '');
|
||||
fs.readFile(sockPath, readCygsocket);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var m;
|
||||
if (m = RE_CYGWIN_SOCK.exec(data.toString('ascii'))) {
|
||||
var port;
|
||||
var secret;
|
||||
var secretbuf;
|
||||
var state;
|
||||
var bc = 0;
|
||||
var isRetrying = false;
|
||||
var inbuf = [];
|
||||
var credsbuf = new Buffer(12);
|
||||
var i;
|
||||
var j;
|
||||
|
||||
// use 0 for pid, uid, and gid to ensure we get an error and also
|
||||
// a valid uid and gid from cygwin so that we don't have to figure it
|
||||
// out ourselves
|
||||
credsbuf.fill(0);
|
||||
|
||||
// parse cygwin unix socket file contents
|
||||
port = parseInt(m[1], 10);
|
||||
secret = m[2].replace(/\-/g, '');
|
||||
secretbuf = new Buffer(16);
|
||||
for (i = 0, j = 0; j < 32; ++i,j+=2)
|
||||
secretbuf[i] = parseInt(secret.substring(j, j + 2), 16);
|
||||
|
||||
// convert to host order (always LE for Windows)
|
||||
for (i = 0; i < 16; i += 4)
|
||||
secretbuf.writeUInt32LE(secretbuf.readUInt32BE(i, true), i, true);
|
||||
|
||||
function _onconnect() {
|
||||
bc = 0;
|
||||
state = 'secret';
|
||||
sock.write(secretbuf);
|
||||
}
|
||||
function _ondata(data) {
|
||||
bc += data.length;
|
||||
if (state === 'secret') {
|
||||
// the secret we sent is echoed back to us by cygwin, not sure of
|
||||
// the reason for that, but we ignore it nonetheless ...
|
||||
if (bc === 16) {
|
||||
bc = 0;
|
||||
state = 'creds';
|
||||
sock.write(credsbuf);
|
||||
}
|
||||
} else if (state === 'creds') {
|
||||
// if this is the first attempt, make sure to gather the valid
|
||||
// uid and gid for our next attempt
|
||||
if (!isRetrying)
|
||||
inbuf.push(data);
|
||||
|
||||
if (bc === 12) {
|
||||
sock.removeListener('connect', _onconnect);
|
||||
sock.removeListener('data', _ondata);
|
||||
sock.removeListener('close', _onclose);
|
||||
if (isRetrying) {
|
||||
addSockListeners();
|
||||
sock.emit('connect');
|
||||
} else {
|
||||
isRetrying = true;
|
||||
credsbuf = Buffer.concat(inbuf);
|
||||
credsbuf.writeUInt32LE(process.pid, 0, true);
|
||||
sock.destroy();
|
||||
tryConnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function _onclose() {
|
||||
cb(new Error('Problem negotiating cygwin unix socket security'));
|
||||
}
|
||||
function tryConnect() {
|
||||
sock = new Socket();
|
||||
sock.once('connect', _onconnect);
|
||||
sock.on('data', _ondata);
|
||||
sock.once('close', _onclose);
|
||||
sock.connect(port);
|
||||
}
|
||||
tryConnect();
|
||||
} else
|
||||
cb(new Error('Malformed cygwin unix socket file'));
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else
|
||||
sock = new Socket();
|
||||
|
||||
function addSockListeners() {
|
||||
if (!accept && !reject) {
|
||||
sock.once('connect', onconnect);
|
||||
sock.on('data', ondata);
|
||||
sock.once('error', onerror);
|
||||
sock.once('close', onclose);
|
||||
} else {
|
||||
var chan;
|
||||
sock.once('connect', function() {
|
||||
chan = accept();
|
||||
var isDone = false;
|
||||
function onDone() {
|
||||
if (isDone)
|
||||
return;
|
||||
sock.destroy();
|
||||
isDone = true;
|
||||
}
|
||||
chan.once('end', onDone)
|
||||
.once('close', onDone)
|
||||
.on('data', function(data) {
|
||||
sock.write(data);
|
||||
});
|
||||
sock.on('data', function(data) {
|
||||
chan.write(data);
|
||||
});
|
||||
});
|
||||
sock.once('close', function() {
|
||||
if (!chan)
|
||||
reject();
|
||||
});
|
||||
}
|
||||
}
|
||||
addSockListeners();
|
||||
sock.connect(sockPath);
|
||||
};
|
||||
|
||||
|
||||
// win32 only ------------------------------------------------------------------
|
||||
if (process.platform === 'win32') {
|
||||
var RET_ERR_BADARGS = 10;
|
||||
var RET_ERR_UNAVAILABLE = 11;
|
||||
var RET_ERR_NOMAP = 12;
|
||||
var RET_ERR_BINSTDIN = 13;
|
||||
var RET_ERR_BINSTDOUT = 14;
|
||||
var RET_ERR_BADLEN = 15;
|
||||
|
||||
var ERROR = {};
|
||||
var EXEPATH = path.resolve(__dirname, '..', 'util/pagent.exe');
|
||||
ERROR[RET_ERR_BADARGS] = new Error('Invalid pagent.exe arguments');
|
||||
ERROR[RET_ERR_UNAVAILABLE] = new Error('Pageant is not running');
|
||||
ERROR[RET_ERR_NOMAP] = new Error('pagent.exe could not create an mmap');
|
||||
ERROR[RET_ERR_BINSTDIN] = new Error('pagent.exe could not set mode for stdin');
|
||||
ERROR[RET_ERR_BINSTDOUT] = new Error('pagent.exe could not set mode for stdout');
|
||||
ERROR[RET_ERR_BADLEN] = new Error('pagent.exe did not get expected input payload');
|
||||
|
||||
function PageantSock() {
|
||||
this.proc = undefined;
|
||||
this.buffer = null;
|
||||
}
|
||||
inherits(PageantSock, EventEmitter);
|
||||
|
||||
PageantSock.prototype.write = function(buf) {
|
||||
if (this.buffer === null)
|
||||
this.buffer = buf;
|
||||
else {
|
||||
this.buffer = Buffer.concat([this.buffer, buf],
|
||||
this.buffer.length + buf.length);
|
||||
}
|
||||
// Wait for at least all length bytes
|
||||
if (this.buffer.length < 4)
|
||||
return;
|
||||
|
||||
var len = this.buffer.readUInt32BE(0, true);
|
||||
// Make sure we have a full message before querying pageant
|
||||
if ((this.buffer.length - 4) < len)
|
||||
return;
|
||||
|
||||
buf = this.buffer.slice(0, 4 + len);
|
||||
if (this.buffer.length > (4 + len))
|
||||
this.buffer = this.buffer.slice(4 + len);
|
||||
else
|
||||
this.buffer = null;
|
||||
|
||||
var self = this;
|
||||
var proc;
|
||||
var hadError = false;
|
||||
proc = this.proc = cp.spawn(EXEPATH, [ buf.length ]);
|
||||
proc.stdout.on('data', function(data) {
|
||||
self.emit('data', data);
|
||||
});
|
||||
proc.once('error', function(err) {
|
||||
if (!hadError) {
|
||||
hadError = true;
|
||||
self.emit('error', err);
|
||||
}
|
||||
});
|
||||
proc.once('close', function(code) {
|
||||
self.proc = undefined;
|
||||
if (ERROR[code] && !hadError) {
|
||||
hadError = true;
|
||||
self.emit('error', ERROR[code]);
|
||||
}
|
||||
self.emit('close', hadError);
|
||||
});
|
||||
proc.stdin.end(buf);
|
||||
};
|
||||
PageantSock.prototype.end = PageantSock.prototype.destroy = function() {
|
||||
this.buffer = null;
|
||||
if (this.proc) {
|
||||
this.proc.kill();
|
||||
this.proc = undefined;
|
||||
}
|
||||
};
|
||||
PageantSock.prototype.connect = function() {
|
||||
this.emit('connect');
|
||||
};
|
||||
}
|
||||
1540
build/node_modules/ssh2/lib/client.js
generated
vendored
Normal file
1540
build/node_modules/ssh2/lib/client.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
76
build/node_modules/ssh2/lib/keepalivemgr.js
generated
vendored
Normal file
76
build/node_modules/ssh2/lib/keepalivemgr.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
var spliceOne = require('./utils').spliceOne;
|
||||
|
||||
function Manager(interval, streamInterval, kaCountMax) {
|
||||
var streams = this._streams = [];
|
||||
this._timer = undefined;
|
||||
this._timerInterval = interval;
|
||||
this._timerfn = function() {
|
||||
var now = Date.now();
|
||||
for (var i = 0, len = streams.length, s, last; i < len; ++i) {
|
||||
s = streams[i];
|
||||
last = s._kalast;
|
||||
if (last && (now - last) >= streamInterval) {
|
||||
if (++s._kacnt > kaCountMax) {
|
||||
var err = new Error('Keepalive timeout');
|
||||
err.level = 'client-timeout';
|
||||
s.emit('error', err);
|
||||
s.disconnect();
|
||||
spliceOne(streams, i);
|
||||
--i;
|
||||
len = streams.length;
|
||||
} else {
|
||||
s._kalast = now;
|
||||
// XXX: if the server ever starts sending real global requests to the
|
||||
// client, we will need to add a dummy callback here to keep the
|
||||
// correct reply order
|
||||
s.ping();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Manager.prototype.start = function() {
|
||||
if (this._timer)
|
||||
this.stop();
|
||||
this._timer = setInterval(this._timerfn, this._timerInterval);
|
||||
};
|
||||
|
||||
Manager.prototype.stop = function() {
|
||||
if (this._timer) {
|
||||
clearInterval(this._timer);
|
||||
this._timer = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
Manager.prototype.add = function(stream) {
|
||||
var streams = this._streams,
|
||||
self = this;
|
||||
|
||||
stream.once('end', function() {
|
||||
self.remove(stream);
|
||||
}).on('packet', resetKA);
|
||||
|
||||
streams[streams.length] = stream;
|
||||
|
||||
resetKA();
|
||||
|
||||
if (!this._timer)
|
||||
this.start();
|
||||
|
||||
function resetKA() {
|
||||
stream._kalast = Date.now();
|
||||
stream._kacnt = 0;
|
||||
}
|
||||
};
|
||||
|
||||
Manager.prototype.remove = function(stream) {
|
||||
var streams = this._streams,
|
||||
index = streams.indexOf(stream);
|
||||
if (index > -1)
|
||||
spliceOne(streams, index);
|
||||
if (!streams.length)
|
||||
this.stop();
|
||||
};
|
||||
|
||||
module.exports = Manager;
|
||||
1157
build/node_modules/ssh2/lib/server.js
generated
vendored
Normal file
1157
build/node_modules/ssh2/lib/server.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5
build/node_modules/ssh2/lib/utils.js
generated
vendored
Normal file
5
build/node_modules/ssh2/lib/utils.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
exports.spliceOne = function(list, index) {
|
||||
for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
|
||||
list[i] = list[k];
|
||||
list.pop();
|
||||
};
|
||||
71
build/node_modules/ssh2/package.json
generated
vendored
Normal file
71
build/node_modules/ssh2/package.json
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"_from": "ssh2@^0.5.1",
|
||||
"_id": "ssh2@0.5.5",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-x3gezS7OcwSiU89iD6taXCK7IjU=",
|
||||
"_location": "/ssh2",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "ssh2@^0.5.1",
|
||||
"name": "ssh2",
|
||||
"escapedName": "ssh2",
|
||||
"rawSpec": "^0.5.1",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^0.5.1"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/sftp-promises"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.5.5.tgz",
|
||||
"_shasum": "c7781ecd2ece7304a253cf620fab5a5c22bb2235",
|
||||
"_spec": "ssh2@^0.5.1",
|
||||
"_where": "/Users/asciidisco/Desktop/asciidisco.com/build/node_modules/sftp-promises",
|
||||
"author": {
|
||||
"name": "Brian White",
|
||||
"email": "mscdex@mscdex.net"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/mscdex/ssh2/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"ssh2-streams": "~0.1.18"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "SSH2 client and server modules written in pure JavaScript for node.js",
|
||||
"devDependencies": {
|
||||
"semver": "^5.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"homepage": "https://github.com/mscdex/ssh2#readme",
|
||||
"keywords": [
|
||||
"ssh",
|
||||
"ssh2",
|
||||
"sftp",
|
||||
"secure",
|
||||
"shell",
|
||||
"exec",
|
||||
"remote",
|
||||
"client"
|
||||
],
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://github.com/mscdex/ssh2/raw/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"main": "./lib/client",
|
||||
"name": "ssh2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@github.com/mscdex/ssh2.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test/test.js"
|
||||
},
|
||||
"version": "0.5.5"
|
||||
}
|
||||
26
build/node_modules/ssh2/test/fixtures/bad_rsa_private_key
generated
vendored
Normal file
26
build/node_modules/ssh2/test/fixtures/bad_rsa_private_key
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAz7MF4vhgw6HxNf3KtVf3VULTYgrRSlv+cCZdB1xxI1p/nGyu
|
||||
/eekUn5C+mGeDS488DX5ulzicxVpL7pamc/tFNcp91MrR7PiIMK2l+bwbZJubbLj
|
||||
DHhNcBklnFOSKxtmQRfuorGakpy/kXmIxF5of0xXGns6DlHRq9dGCJIXvrkqhcEb
|
||||
k4n2y4aV4VOiMHdo6FrFQVPzA8DlbJP2SjIFZ/0VdK7O7eiyiqV1p1xlbTQQ5rAX
|
||||
LdsshBn/GvoBOTCVupMXurn2582vgGh26Mmovj2QGzScMGUVttkMlnxUmKT/aQka
|
||||
mC0vR54QOW7lyWPjAitOV0qgmtGm3/cl7W7NjwIDAQABAoIBAFxH0C+951BEXWV9
|
||||
s1jLEqshG8YNxFtjcDLn+KFSoznv9Y7MgxtwlgPI8X1Jbe2xQ4X+lUwGBN7Y/nkk
|
||||
NSjtxwphZtXqb+pVs/yWRoZLJzunucSnnFVoBg/uPFWuk9zvOYlmVrKWcnT9i+fY
|
||||
tbl5sLgOdQzg/zRpidztssIQFti3o2jnpyrEGcepPWLkfCgqPfGmNv78BAIt/6iT
|
||||
zYDB4GMSq/LnPTIOFsIOvlkZg3RCcLWeAPRC+lvFQVY+M/uJL5WIbA5il1IMMKH7
|
||||
MULWpRO3lnb1JVrkZlBldK5uew6AN3tHDQOmg+C2JuIbOZ35J9dcnwsE+IptWWBj
|
||||
XiFRJCECgYEA8BeuufkslureqOycaPLMkqchMTue1OxbLJFvPN+dh/cW6Lng3b8+
|
||||
xAyzZrc0vccH/jl9WVHhIZ7TcKXDzSmmrtnZ/3m1c4gANGqIPwO+emL1ZzzkIKGd
|
||||
FrLeBZKP4TWry9kjg4cG1SKGpcB5ngJMPXUxMZNe74tC4Hk820PkFjcCgYEA3XXn
|
||||
ngRCgH9N1eKSD2daxxlBhTTSnTgjU+dDaDFQzPIhJCcS8HwyQBQmNTOSXXK9sShC
|
||||
fdXAsmiBby5WEBq/K5+cXeDG2ZlFLyPovEgTUrLgraw42PYs0+A8Ls7dFk7PuMez
|
||||
3G2gUPkY039JiyXKfcog9/dIRfbWCwzQ6s7TV2kCgYEArsme81cahhgg1zvCNokk
|
||||
M1Omz2/HFt2nFpAeOmPVDGnu7Kh9sxGKgTF53bpclBh0kjiKL99zFYXKCoUzQYYk
|
||||
CcEhemLBnYUSGRbBb5arMfAfFfR3Y+YkNaUsC0SCqILpOfMvbo57g+ipu7ufDlA/
|
||||
7rIFiUDvaVap7j909W+8egsCgYEAsuc/0DBixMmSyHl7QwRcmkC15HVSu32RVIOb
|
||||
ub01KAtmaH1EWJAMTCW64/mggOtjgI0kgeE/BSFVhsqo7eOdkhEj0db27OxbroRU
|
||||
zF1xdrpYtRRO7D6a4iLgm3OzuQS72+tASo8pFqDUxG6sq8NAvLOgRJE4ioSoT07w
|
||||
KvAgXRkCgYEAmWgcsX/BdNcKOteSDtPkys5NRtWCBz7Coxb+xXXoXz1FVegBolpY
|
||||
wXVePvXTIbU8VJOLunMyH5wpmMUiJbTX9v2o/yfpsH0ci4GaAeVtqpA=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
12
build/node_modules/ssh2/test/fixtures/id_dsa
generated
vendored
Normal file
12
build/node_modules/ssh2/test/fixtures/id_dsa
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
-----BEGIN DSA PRIVATE KEY-----
|
||||
MIIBuwIBAAKBgQC3/2VIGHgqHuxvhPa6rryqqLy6sQmjeSIwyrIW5F/o8W4sz/mE
|
||||
0noDSW4PaoXjgPQv5egj1EByws6dMOUqLaZHNWNn+Lh/jkKlwKyhbSCAjqoWH3v3
|
||||
uI1j58GO/eZ2+REijfyA0XJxdm7kqEexxbg0UpFr1F/eLBUxpLIbhhS1cwIVAKcB
|
||||
B9DnAObuPJGTwYTCaIIBQDy9AoGAJicW0pIFwgoTYsIeywmUQopJ3FQ4M3eDwQ0U
|
||||
T33pzWvBZFN2OsUDTFg64PNm9ow09wk042qMg168eKCUTp2iR/Y9R4xTj8dls8iv
|
||||
aMGMZ/B32eURIjUREGiXYTyG1pfuB2znSvr/5pavhuz5yG9M0AJCiYiexdaQKO3N
|
||||
oJp6T3ACgYEAsep79p4WljnawrJc928zGq6dLYjs+5apYhqx4vf2l3Z2u26VqVNG
|
||||
i5zZkUzhWQYV3/qtEOpO43dyZTHW+d9L8ni6HbXFWRVx60WE+5WKkzkimHJ6gox2
|
||||
kDvOqPudiS34KJOCEYYLEnJmK8aUZBZzWFORXkN8QgA/h9ts8AU785UCFAVXZMWq
|
||||
CteWCH2HzcY2x/65dMwL
|
||||
-----END DSA PRIVATE KEY-----
|
||||
5
build/node_modules/ssh2/test/fixtures/id_ecdsa
generated
vendored
Normal file
5
build/node_modules/ssh2/test/fixtures/id_ecdsa
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIPMZuWP7fMsZeyC1XXVUALVebJOX7PTwmsPql9qG25SeoAoGCCqGSM49
|
||||
AwEHoUQDQgAEB/B6mC5lrekKPWfGEkKpnCk08+dRnzFUg2jUHpaIrOTt4jGdvq6T
|
||||
yAN57asB+PYmFyVIpi35NcmicF18qX3ayg==
|
||||
-----END EC PRIVATE KEY-----
|
||||
15
build/node_modules/ssh2/test/fixtures/id_rsa
generated
vendored
Normal file
15
build/node_modules/ssh2/test/fixtures/id_rsa
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQDL0yFO4W4xbdrJk/i+CW3itPATvhRkS+x+gKmkdH739AqWYP6r
|
||||
kTFAmFTw9gLJ/c2tN7ow0T0QUR9iUsv/3QzTuwsjBu0feo3CVxwMkaJTo5ks9XBo
|
||||
OW0R3tyCcOLlAcQ1WjC7cv5Ifn4gXLLM+k8/y/m3u8ERtidNxbRqpQ/gPQIDAQAB
|
||||
AoGABirSRC/ABNDdIOJQUXe5knWFGiPTPCGr+zvrZiV8PgZtV5WBvzE6e0jgsRXQ
|
||||
icobMhWQla+PGHJL786vi4NlwuhwKcF7Pd908ofej1eeBOd1u/HQ/qsfxPdxI0zF
|
||||
dcWPYgAOo9ydOMGcSx4v1zDIgFInELJzKbv64LJQD0/xhoUCQQD7KhJ7M8Nkwsr2
|
||||
iKCyWTFM2M8/VKltgaiSmsNKZETashk5tKOrM3EWX4RcB/DnvHe8VNyYpC6Sd1uQ
|
||||
AHwPDfxDAkEAz7+7hDybH6Cfvmr8kUOlDXiJJWXp5lP37FLzMDU6a9wTKZFnh57F
|
||||
e91zRmKlQTegFet93MXaFYljRkI+4lMpfwJBAPPLbNEF973Qjq4rBMDZbs9HDDRO
|
||||
+35+AqD7dGC7X1Jg2bd3rf66GiU7ZgDm/GIUQK0gOlg31bT6AniO39zFGH0CQFBh
|
||||
Yd9HR8nT7xrQ8EoQPzNYGNBUf0xz3rAcZCWZ4rHK48sojEMoBkbnputrzX7PU+xH
|
||||
QlqCXuAIWVXc2dHd1WcCQQDIUJHPOsgeAfTLoRRRURp/m8zZ9IpbaPTyDstPVNYe
|
||||
zARW3Oa/tzPqdO6NWaetCp17u7Kb6X9np7Vz17i/4KED
|
||||
-----END RSA PRIVATE KEY-----
|
||||
26
build/node_modules/ssh2/test/fixtures/id_rsa.ppk
generated
vendored
Normal file
26
build/node_modules/ssh2/test/fixtures/id_rsa.ppk
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
PuTTY-User-Key-File-2: ssh-rsa
|
||||
Encryption: none
|
||||
Comment: rsa-key-20150522
|
||||
Public-Lines: 6
|
||||
AAAAB3NzaC1yc2EAAAABJQAAAQB1quqP0rhl78NOLD4lj+1x5FGAqZ3aqo6GiEPz
|
||||
KOaQmy86FuJMK0nHj3gUKTa/Kvaa+8PZyeu+uVseHg47YrynCOcJEEnpqvbArc8M
|
||||
xMWuUnTUMrjvokGDOBBiQu4UAE4bybpgXkNHJfbrcDVgivmv3Ikn8PVIZ1rLBMLZ
|
||||
6Lzn0rjPjFD0X4WqsAJW2SFiZnsjMZtVL2TWadNTyyfjjm2NCRBvd32VLohkSe9Q
|
||||
BZBD6MW8YQyBKUnEF/7WNY0eehDVrfx1YqPOV1bDwFUhRaAYpLDLDR0KCAPvx7qb
|
||||
8G5Cq0TIBsEr3H8ztNRcOTQoaKgn0T18M7cyS4ykoNLYW4Zx
|
||||
Private-Lines: 14
|
||||
AAABACyF3DZraF3sBLXLjSL4MFSblHXfUHxAiPSiQzlpa/9dUCPRTrUJddzOgHZU
|
||||
yJtcXU9mLm4VDRe7wZyxbSs6Hd5WZUGzIuLLEUH8k4hKdE/MLDSdkhV7qhX5iaij
|
||||
tAeRaammRoVUGXTd7rnzGx2cXnnkvkZ22VmqkQ6MLg1DTmWNfOO9cdwFGdQawf/n
|
||||
yUV0nTkWsHXy5Qrozq9wRFk8eyw+pFllxqavsNftZX8VDiQt27JLZPTU4LGkH660
|
||||
3gq1KhNS/l05TlXnMZGjlcPN8UEaBzmCWRezhJSttjs5Kgp1K3yDf4ozMR/HWOCj
|
||||
Jq8fd3VIgli6ML8yjr/c0A0T9MUAAACBAL1/byxHiCvY/2C+/L5T+ZZq13jdZuYK
|
||||
MmOFaNITgEdNGWSIFYRzhLKGXj7awQWOIW6chj470GNOfQjFL1TvXhbwfqW6esDa
|
||||
kETOYQPYQHZijABcn7uurMUm/bu5x/z9gYkAfniOCI5vmvMvJ09JcZ0iUmFWDZZY
|
||||
fAutBvrt+n/vAAAAgQCe9jrA51wn1/wzKmWF+2+OWFUG9usheIcEbHB8mxLguLfU
|
||||
+x4i+2vLo0FtXEPAw+Bt7Tge4t0m6USiVZXtW/QKsh0kMj4mNVHFz+XXw4l1QOYv
|
||||
n5TjnLepiP7majXv4GHI2eOcHkyly4sIkj4jNLYqvT86hMxW4IC+jtJEWhn/nwAA
|
||||
AIEAlJ8cExu2WrWukTDJQHrVegtvdJUhNjol2wLucPuWwSxKuB8FHYwaPRYRkf3d
|
||||
DkZ53hhjJZ0BVkAaQ28uqM09xKD+q1H4/r0nnbtlV4uHLl3cCD5mGrH8I/iDPJX4
|
||||
fFIqCa0+n1D6RzvDqs1QIu+PGSp0K6vHOOS5fP0ZpuT025E=
|
||||
Private-MAC: 4ca26008c85b901f4d2766b0924c25e527678d7e
|
||||
30
build/node_modules/ssh2/test/fixtures/id_rsa_enc
generated
vendored
Normal file
30
build/node_modules/ssh2/test/fixtures/id_rsa_enc
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,CCE70744FB28F2EFB1D74377281A780C
|
||||
|
||||
1WiGnqpSGXFIg+WYr7T2XN72C1YrNQ1jmRISb32TB/Rh2Zo47fjyQnv9impz8b6m
|
||||
91R/qF7uCLI0fswvT5oqwn1L0vUAA0YtW/E2IQJEx5GPiaexoDJYYfu2yy036Kca
|
||||
e9VtCajgrV+kycg1CknCxQKMcKXNq8Czvq66PM4Bzknek5hhdmxHxOl0QAE+8EXt
|
||||
pnasOGz3szTUKkD6givwWgvDXY3BnVG46fXff99Xqgb6fx5IDbAkVKaxWIN/c81E
|
||||
b0rcfyoLb7yjPgNYn9vUI6Z+24NMYUYARzb3dG5geaeX0BYb/VlCtJUsP0Rp2P2P
|
||||
jl+cdvBKaeOvA9gPo/jAtSOFexQRs7AzKzoOLYU1fokd8HhqxOKAljn9ujmEqif7
|
||||
qcimk2s7ff6tSSlxtRzDP+Uq9d1u5tyaONRV2lwj+GdP1gRoOmdZL5chdvoAi0I8
|
||||
5eMf58hEuN2d4h4FryO6z7K+XQ9oo6/N/xHU0U/t2Pco9oY2L6oWMDxKwbfPhaD5
|
||||
CcoEElsK4XFArYDielEq9Y1sXaEuwR5I0ksDDsANp74r9Bhcqz60gJa6hVz0ouEU
|
||||
QA67wV9+TRmulKRxwANvqxQwqPuxqcTPeJjXSUN/ZCaDwYmI+d1poxMx2fQzT82M
|
||||
onlgOWq+3HbCotyoeFpCameymwDQzmrYdMBr7oWLgnOrxmJ89zDc6+jkHFgQJvnU
|
||||
atyeVDqe866ZvvIGWS+r/EsDjV3cTW/cJvdsC+5BpnoXoVF4LqxE3LFbEbQBvqio
|
||||
4enCZpspQSMOJra37vSofbD+DyI5Wd+y8SBmfDLjyDFhT0spW9aN99uFqSc3UElA
|
||||
SAmnFmpYBFEQrRGpvpu5sC0c/YjZeRXr0/F1xPpIT1SWzpRsbcsWRBDzWjLOKWQx
|
||||
8ytwc2QS7eKedfqkPWpYKW0Qtps+XgnGWA6PBX42IYhLsKANRfhFXQv5LPqLNNOn
|
||||
3EsG9pd+0dBpfxFQfyyAKAUuvpJNgJ6kNx8VSj8Ppj8lyUdGa9YucgB02m7gHC9U
|
||||
A4YyJsIcjo6IcrjM+ez1govRRS0nE8AUb8ups9tn8mdBwqcPCrgcJhV7JkOYNJYh
|
||||
NAh0vgmneOq8LSVs2SRaL3uuLNbjh1LR9iViwbIY8kMQXkiXa2/V+PFwt5oqeX5f
|
||||
2x3yzCeGBiQW10InyBBnKutbPD85R4YJhQ55bOMDSFfGGqwOU1QURiO1NUzf9n/2
|
||||
+E8VE7J/IQoO0TrJpC+EV0ROKME9W6+AvEFdmdIigbq3bkdEgSixyLnrhV8V8T4N
|
||||
nbKlLoqfXt8DmT+h8XPzgsu0Fq/PNi6xBaiUsaN9tK6OP2ZVjr9ihbeLTI0rcKDr
|
||||
XX2cWPvTcboRLt+S4wmqchMf7Kxa2PfX5Tf+KCcdZNQO4YqS23wQZgk61kuOQCsS
|
||||
uOop+ICI7yWZkjqCOzGOeHLl/7FyFeprsFDIwD1g20y9bzibbJlbQPhwXSalqDQT
|
||||
MWLH3rdFuvgLH7ujtjxSakES+VzkOhbnmb/Wypbl1D7P7GT2seau16EEGQDhDzcJ
|
||||
Q4d/BjR2WqqxmC79MOAvUWAu6fZQjPD30/gYPGpMaEuiLrDlzDqvf+oi4A9+EtRL
|
||||
-----END RSA PRIVATE KEY-----
|
||||
12
build/node_modules/ssh2/test/fixtures/ssh_host_dsa_key
generated
vendored
Normal file
12
build/node_modules/ssh2/test/fixtures/ssh_host_dsa_key
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
-----BEGIN DSA PRIVATE KEY-----
|
||||
MIIBuwIBAAKBgQDEK+daQ7RuajwxkmBmogb0iUSi/w2RYKuvC2EiviBu3S2s9Bfq
|
||||
gROKscAnURrxpTOa+iYeI7hRzfuX0qFmnFwXIjKJBjqBdg9r76UR5UNytnWQkJ5x
|
||||
lxsZThMeAMw38SvmRMw15kkgxycKGqu4yvNLGyVwN02bPVjLcEVLWLCM1wIVAK50
|
||||
5JqF0nmGXFkcmNtxR24/mNXTAoGBAIc2p8C8b08OTQPmfZI+Wq8a+CuEr5R36bMW
|
||||
TAs5etqmO2aVo5zvR0MnTjoS2ZDbuznDG9RiSuIB+ivr/daEwi+K+Ha8pZfYjXCG
|
||||
ldzvmr5I4x8rkH3zyn7BADnc+/q3pa8AnZvTme5eNsxn1Pu/rmC/8KKnhmzRggqP
|
||||
N8ORhoQQAoGAMCvoMcsDAui2d/WVpgHZZEFlxfbf4dPUPYb5zf2xOiMG9OK+Cbv3
|
||||
NaLZwk/Hd2g4L3nwTKDASxfmRcrbuaOg/d7aDjQ2mJz18Js4IjY34QpgLspGCNX/
|
||||
6rJSQ+ov1Z2Etr95N4Tzm3qpxW5BH9TTgaC/ntb9NRqIzNPCvAHXmlcCFBxgZpyb
|
||||
4GUgmqhTOMtmBkJ7QpL9
|
||||
-----END DSA PRIVATE KEY-----
|
||||
5
build/node_modules/ssh2/test/fixtures/ssh_host_ecdsa_key
generated
vendored
Normal file
5
build/node_modules/ssh2/test/fixtures/ssh_host_ecdsa_key
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEICrdbIIYmW/XTK9hxaQZZ56IGwG0NhqD2eppYUJNZsECoAoGCCqGSM49
|
||||
AwEHoUQDQgAEa+MuLv++3ft5HPFIsM2hQnmHPF12q08/MaHoGud4yqp3evyomjZN
|
||||
xbsSb39fv8t6XX1u1rm5oHQcBV5Mqomaeg==
|
||||
-----END EC PRIVATE KEY-----
|
||||
15
build/node_modules/ssh2/test/fixtures/ssh_host_rsa_key
generated
vendored
Normal file
15
build/node_modules/ssh2/test/fixtures/ssh_host_rsa_key
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQC57UB/5H0M+t+mopksrltCCIXghryzofJjau+8tuMT9CG6ta3S
|
||||
O9aKApJUUG/xtc88giVhB7HFABX/oob+jrkSthR8s/whULC8E+GhvOBjHydRUZIs
|
||||
aPYOMBb42HcbOsgq3li/hwOcDk0vY00hZDKCum9BgvRAb7dPEkw2dmiCQQIDAQAB
|
||||
AoGAMG+HOwoaLbR5aR64yrQNYBF6Vvii1iUdURr9o2r9kygpVUuZIcim5kMvPbnK
|
||||
v+w+NaQt+q4XeJvCH1uG0W/69FwnphfaOVmCCUtsoJ6sU3fWr9x59MtKL2Llh8xR
|
||||
50lz6R+eDXoYRDq245hG9BFn/bu0vtqQqx06mlZJcjaRocECQQDjdYFmr+DSww3x
|
||||
VNx0G0DUkaQZZ+iqZiT3Zund2pcBB4aLiewOrqj0GFct4+YNzgxIXPejmS0eSokN
|
||||
N2lC3NxZAkEA0UGjN5TG5/LEK3zcYtx2kpXryenrYORo1n2L/WPMZ0mjLQyd4LJr
|
||||
ibfgVUfwX/kV3vgGYLwjpgcaTiMsecv4KQJAYMmMgZSPdz+WvD1e/WznXkyG5mSn
|
||||
xXJngnrhQw0TulVodBIBR5IcxJli510VdIRcB6K/oXa5ky0mOmB8wv3WKQJBAKEF
|
||||
PxE//KbzWhyUogm4180IbD4dMDCI0ltqlFRRfTJlqZi6wqnq4XFB+u/kwYU4aKoA
|
||||
dPfvDgduI8HIsyqt17ECQDI/HC8PiYsDIOyVpQuQdIAsbGmoavK7X1MVEWR2nj9t
|
||||
7BbUVFSnVKynL4TWIJZ6xP8WQwkDBQc5WjognHDaUTQ=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
2135
build/node_modules/ssh2/test/test-client-server.js
generated
vendored
Normal file
2135
build/node_modules/ssh2/test/test-client-server.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
459
build/node_modules/ssh2/test/test-openssh.js
generated
vendored
Normal file
459
build/node_modules/ssh2/test/test-openssh.js
generated
vendored
Normal file
@@ -0,0 +1,459 @@
|
||||
var Server = require('../lib/server');
|
||||
var utils = require('ssh2-streams').utils;
|
||||
|
||||
var semver = require('semver');
|
||||
|
||||
var fs = require('fs');
|
||||
var crypto = require('crypto');
|
||||
var path = require('path');
|
||||
var join = path.join;
|
||||
var assert = require('assert');
|
||||
var spawn = require('child_process').spawn;
|
||||
var exec = require('child_process').exec;
|
||||
|
||||
var t = -1;
|
||||
var group = path.basename(__filename, '.js') + '/';
|
||||
var fixturesdir = join(__dirname, 'fixtures');
|
||||
|
||||
var CLIENT_TIMEOUT = 5000;
|
||||
var USER = 'nodejs';
|
||||
var HOST_KEY_RSA = fs.readFileSync(join(fixturesdir, 'ssh_host_rsa_key'));
|
||||
var HOST_KEY_DSA = fs.readFileSync(join(fixturesdir, 'ssh_host_dsa_key'));
|
||||
var HOST_KEY_ECDSA = fs.readFileSync(join(fixturesdir, 'ssh_host_ecdsa_key'));
|
||||
var CLIENT_KEY_RSA_PATH = join(fixturesdir, 'id_rsa');
|
||||
var CLIENT_KEY_RSA = fs.readFileSync(CLIENT_KEY_RSA_PATH);
|
||||
var CLIENT_KEY_RSA_PUB = utils.genPublicKey(utils.parseKey(CLIENT_KEY_RSA));
|
||||
var CLIENT_KEY_DSA_PATH = join(fixturesdir, 'id_dsa');
|
||||
var CLIENT_KEY_DSA = fs.readFileSync(CLIENT_KEY_DSA_PATH);
|
||||
var CLIENT_KEY_DSA_PUB = utils.genPublicKey(utils.parseKey(CLIENT_KEY_DSA));
|
||||
if (semver.gte(process.version, '5.2.0')) {
|
||||
var CLIENT_KEY_ECDSA_PATH = join(fixturesdir, 'id_ecdsa');
|
||||
var CLIENT_KEY_ECDSA = fs.readFileSync(CLIENT_KEY_ECDSA_PATH);
|
||||
var CLIENT_KEY_ECDSA_PUB = utils.genPublicKey(
|
||||
utils.parseKey(CLIENT_KEY_ECDSA)
|
||||
);
|
||||
}
|
||||
var opensshVer;
|
||||
var DEBUG = false;
|
||||
|
||||
// Fix file modes to avoid OpenSSH client complaints about keys' permissions
|
||||
fs.readdirSync(fixturesdir).forEach(function(file) {
|
||||
fs.chmodSync(join(fixturesdir, file), '0600');
|
||||
});
|
||||
|
||||
var tests = [
|
||||
{ run: function() {
|
||||
var what = this.what;
|
||||
var server;
|
||||
|
||||
server = setup(
|
||||
this,
|
||||
{ privateKeyPath: CLIENT_KEY_RSA_PATH },
|
||||
{ hostKeys: [HOST_KEY_RSA] }
|
||||
);
|
||||
|
||||
server.on('connection', function(conn) {
|
||||
conn.on('authentication', function(ctx) {
|
||||
if (ctx.method === 'none')
|
||||
return ctx.reject();
|
||||
assert(ctx.method === 'publickey',
|
||||
makeMsg(what, 'Unexpected auth method: ' + ctx.method));
|
||||
assert(ctx.username === USER,
|
||||
makeMsg(what, 'Unexpected username: ' + ctx.username));
|
||||
assert(ctx.key.algo === 'ssh-rsa',
|
||||
makeMsg(what, 'Unexpected key algo: ' + ctx.key.algo));
|
||||
assert.deepEqual(CLIENT_KEY_RSA_PUB.public,
|
||||
ctx.key.data,
|
||||
makeMsg(what, 'Public key mismatch'));
|
||||
if (ctx.signature) {
|
||||
var verifier = crypto.createVerify('RSA-SHA1');
|
||||
var pem = CLIENT_KEY_RSA_PUB.publicOrig;
|
||||
verifier.update(ctx.blob);
|
||||
assert(verifier.verify(pem, ctx.signature),
|
||||
makeMsg(what, 'Could not verify PK signature'));
|
||||
ctx.accept();
|
||||
} else
|
||||
ctx.accept();
|
||||
}).on('ready', function() {
|
||||
conn.on('session', function(accept, reject) {
|
||||
var session = accept();
|
||||
if (session) {
|
||||
session.on('exec', function(accept, reject) {
|
||||
var stream = accept();
|
||||
if (stream) {
|
||||
stream.exit(0);
|
||||
stream.end();
|
||||
}
|
||||
}).on('pty', function(accept, reject) {
|
||||
accept && accept();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
what: 'Authenticate with an RSA key'
|
||||
},
|
||||
{ run: function() {
|
||||
var what = this.what;
|
||||
var server;
|
||||
|
||||
server = setup(
|
||||
this,
|
||||
{ privateKeyPath: CLIENT_KEY_DSA_PATH },
|
||||
{ hostKeys: [HOST_KEY_RSA] }
|
||||
);
|
||||
|
||||
server.on('connection', function(conn) {
|
||||
conn.on('authentication', function(ctx) {
|
||||
if (ctx.method === 'none')
|
||||
return ctx.reject();
|
||||
assert(ctx.method === 'publickey',
|
||||
makeMsg(what, 'Unexpected auth method: ' + ctx.method));
|
||||
assert(ctx.username === USER,
|
||||
makeMsg(what, 'Unexpected username: ' + ctx.username));
|
||||
assert(ctx.key.algo === 'ssh-dss',
|
||||
makeMsg(what, 'Unexpected key algo: ' + ctx.key.algo));
|
||||
assert.deepEqual(CLIENT_KEY_DSA_PUB.public,
|
||||
ctx.key.data,
|
||||
makeMsg(what, 'Public key mismatch'));
|
||||
if (ctx.signature) {
|
||||
var verifier = crypto.createVerify('DSA-SHA1');
|
||||
var pem = CLIENT_KEY_DSA_PUB.publicOrig;
|
||||
verifier.update(ctx.blob);
|
||||
assert(verifier.verify(pem, ctx.signature),
|
||||
makeMsg(what, 'Could not verify PK signature'));
|
||||
ctx.accept();
|
||||
} else
|
||||
ctx.accept();
|
||||
}).on('ready', function() {
|
||||
conn.on('session', function(accept, reject) {
|
||||
var session = accept();
|
||||
if (session) {
|
||||
session.on('exec', function(accept, reject) {
|
||||
var stream = accept();
|
||||
if (stream) {
|
||||
stream.exit(0);
|
||||
stream.end();
|
||||
}
|
||||
}).on('pty', function(accept, reject) {
|
||||
accept && accept();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
what: 'Authenticate with a DSA key'
|
||||
},
|
||||
{ run: function() {
|
||||
if (semver.lt(process.version, '5.2.0'))
|
||||
return next();
|
||||
var what = this.what;
|
||||
var server;
|
||||
|
||||
server = setup(
|
||||
this,
|
||||
{ privateKeyPath: CLIENT_KEY_ECDSA_PATH },
|
||||
{ hostKeys: [HOST_KEY_RSA] }
|
||||
);
|
||||
|
||||
server.on('connection', function(conn) {
|
||||
conn.on('authentication', function(ctx) {
|
||||
if (ctx.method === 'none')
|
||||
return ctx.reject();
|
||||
assert(ctx.method === 'publickey',
|
||||
makeMsg(what, 'Unexpected auth method: ' + ctx.method));
|
||||
assert(ctx.username === USER,
|
||||
makeMsg(what, 'Unexpected username: ' + ctx.username));
|
||||
assert(ctx.key.algo === 'ecdsa-sha2-nistp256',
|
||||
makeMsg(what, 'Unexpected key algo: ' + ctx.key.algo));
|
||||
assert.deepEqual(CLIENT_KEY_ECDSA_PUB.public,
|
||||
ctx.key.data,
|
||||
makeMsg(what, 'Public key mismatch'));
|
||||
if (ctx.signature) {
|
||||
var verifier = crypto.createVerify('sha256');
|
||||
var pem = CLIENT_KEY_ECDSA_PUB.publicOrig;
|
||||
verifier.update(ctx.blob);
|
||||
assert(verifier.verify(pem, ctx.signature),
|
||||
makeMsg(what, 'Could not verify PK signature'));
|
||||
ctx.accept();
|
||||
} else
|
||||
ctx.accept();
|
||||
}).on('ready', function() {
|
||||
conn.on('session', function(accept, reject) {
|
||||
var session = accept();
|
||||
if (session) {
|
||||
session.on('exec', function(accept, reject) {
|
||||
var stream = accept();
|
||||
if (stream) {
|
||||
stream.exit(0);
|
||||
stream.end();
|
||||
}
|
||||
}).on('pty', function(accept, reject) {
|
||||
accept && accept();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
what: 'Authenticate with a ECDSA key'
|
||||
},
|
||||
{ run: function() {
|
||||
var server;
|
||||
|
||||
server = setup(
|
||||
this,
|
||||
{ privateKeyPath: CLIENT_KEY_RSA_PATH },
|
||||
{ hostKeys: [HOST_KEY_DSA] }
|
||||
);
|
||||
|
||||
server.on('connection', function(conn) {
|
||||
conn.on('authentication', function(ctx) {
|
||||
ctx.accept();
|
||||
}).on('ready', function() {
|
||||
conn.on('session', function(accept, reject) {
|
||||
var session = accept();
|
||||
if (session) {
|
||||
session.on('exec', function(accept, reject) {
|
||||
var stream = accept();
|
||||
if (stream) {
|
||||
stream.exit(0);
|
||||
stream.end();
|
||||
}
|
||||
}).on('pty', function(accept, reject) {
|
||||
accept && accept();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
what: 'Server with DSA host key'
|
||||
},
|
||||
{ run: function() {
|
||||
if (semver.lt(process.version, '5.2.0'))
|
||||
return next();
|
||||
var server;
|
||||
|
||||
server = setup(
|
||||
this,
|
||||
{ privateKeyPath: CLIENT_KEY_RSA_PATH },
|
||||
{ hostKeys: [HOST_KEY_ECDSA] }
|
||||
);
|
||||
|
||||
server.on('connection', function(conn) {
|
||||
conn.on('authentication', function(ctx) {
|
||||
ctx.accept();
|
||||
}).on('ready', function() {
|
||||
conn.on('session', function(accept, reject) {
|
||||
var session = accept();
|
||||
if (session) {
|
||||
session.on('exec', function(accept, reject) {
|
||||
var stream = accept();
|
||||
if (stream) {
|
||||
stream.exit(0);
|
||||
stream.end();
|
||||
}
|
||||
}).on('pty', function(accept, reject) {
|
||||
accept && accept();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
what: 'Server with ECDSA host key'
|
||||
},
|
||||
{ run: function() {
|
||||
var server;
|
||||
var what = this.what;
|
||||
|
||||
server = setup(
|
||||
this,
|
||||
{ privateKeyPath: CLIENT_KEY_RSA_PATH },
|
||||
{ hostKeys: [HOST_KEY_RSA] }
|
||||
);
|
||||
|
||||
server.on('_child', function(childProc) {
|
||||
childProc.stderr.once('data', function(data) {
|
||||
childProc.stdin.end();
|
||||
});
|
||||
childProc.stdin.write('ping');
|
||||
}).on('connection', function(conn) {
|
||||
conn.on('authentication', function(ctx) {
|
||||
ctx.accept();
|
||||
}).on('ready', function() {
|
||||
conn.on('session', function(accept, reject) {
|
||||
var session = accept();
|
||||
assert(session, makeMsg(what, 'Missing session'));
|
||||
session.on('exec', function(accept, reject) {
|
||||
var stream = accept();
|
||||
assert(stream, makeMsg(what, 'Missing exec stream'));
|
||||
stream.stdin.on('data', function(data) {
|
||||
stream.stdout.write('pong on stdout');
|
||||
stream.stderr.write('pong on stderr');
|
||||
}).on('end', function() {
|
||||
stream.stdout.write('pong on stdout');
|
||||
stream.stderr.write('pong on stderr');
|
||||
stream.exit(0);
|
||||
stream.close();
|
||||
});
|
||||
}).on('pty', function(accept, reject) {
|
||||
accept && accept();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
what: 'Server closes stdin too early'
|
||||
},
|
||||
];
|
||||
|
||||
function setup(self, clientcfg, servercfg) {
|
||||
self.state = {
|
||||
serverReady: false,
|
||||
clientClose: false,
|
||||
serverClose: false
|
||||
};
|
||||
|
||||
var client;
|
||||
var server = new Server(servercfg);
|
||||
|
||||
server.on('error', onError)
|
||||
.on('connection', function(conn) {
|
||||
conn.on('error', onError)
|
||||
.on('ready', onReady);
|
||||
server.close();
|
||||
})
|
||||
.on('close', onClose);
|
||||
|
||||
function onError(err) {
|
||||
var which = (arguments.length >= 3 ? 'client' : 'server');
|
||||
assert(false, makeMsg(self.what, 'Unexpected ' + which + ' error: ' + err));
|
||||
}
|
||||
function onReady() {
|
||||
assert(!self.state.serverReady,
|
||||
makeMsg(self.what, 'Received multiple ready events for server'));
|
||||
self.state.serverReady = true;
|
||||
self.onReady && self.onReady();
|
||||
}
|
||||
function onClose() {
|
||||
if (arguments.length >= 3) {
|
||||
assert(!self.state.clientClose,
|
||||
makeMsg(self.what, 'Received multiple close events for client'));
|
||||
self.state.clientClose = true;
|
||||
} else {
|
||||
assert(!self.state.serverClose,
|
||||
makeMsg(self.what, 'Received multiple close events for server'));
|
||||
self.state.serverClose = true;
|
||||
}
|
||||
if (self.state.clientClose && self.state.serverClose)
|
||||
next();
|
||||
}
|
||||
|
||||
process.nextTick(function() {
|
||||
server.listen(0, 'localhost', function() {
|
||||
var cmd = 'ssh';
|
||||
var args = ['-o', 'UserKnownHostsFile=/dev/null',
|
||||
'-o', 'StrictHostKeyChecking=no',
|
||||
'-o', 'CheckHostIP=no',
|
||||
'-o', 'ConnectTimeout=3',
|
||||
'-o', 'GlobalKnownHostsFile=/dev/null',
|
||||
'-o', 'GSSAPIAuthentication=no',
|
||||
'-o', 'IdentitiesOnly=yes',
|
||||
'-o', 'BatchMode=yes',
|
||||
'-o', 'VerifyHostKeyDNS=no',
|
||||
|
||||
'-vvvvvv',
|
||||
'-T',
|
||||
'-o', 'KbdInteractiveAuthentication=no',
|
||||
'-o', 'HostbasedAuthentication=no',
|
||||
'-o', 'PasswordAuthentication=no',
|
||||
'-o', 'PubkeyAuthentication=yes',
|
||||
'-o', 'PreferredAuthentications=publickey'];
|
||||
if (clientcfg.privateKeyPath)
|
||||
args.push('-o', 'IdentityFile=' + clientcfg.privateKeyPath);
|
||||
if (!/^[0-6]\./.test(opensshVer)) {
|
||||
// OpenSSH 7.0+ disables DSS/DSA host (and user) key support by
|
||||
// default, so we explicitly enable it here
|
||||
args.push('-o', 'HostKeyAlgorithms=+ssh-dss');
|
||||
}
|
||||
args.push('-p', server.address().port.toString(),
|
||||
'-l', USER,
|
||||
'localhost',
|
||||
'uptime');
|
||||
|
||||
client = spawn(cmd, args);
|
||||
server.emit('_child', client);
|
||||
if (DEBUG) {
|
||||
client.stdout.pipe(process.stdout);
|
||||
client.stderr.pipe(process.stderr);
|
||||
} else {
|
||||
client.stdout.resume();
|
||||
client.stderr.resume();
|
||||
}
|
||||
client.on('error', function(err) {
|
||||
onError(err, null, null);
|
||||
}).on('exit', function(code) {
|
||||
clearTimeout(client.timer);
|
||||
if (code !== 0)
|
||||
return onError(new Error('Non-zero exit code ' + code), null, null);
|
||||
onClose(null, null, null);
|
||||
});
|
||||
|
||||
client.timer = setTimeout(function() {
|
||||
assert(false, makeMsg(self.what, 'Client timeout'));
|
||||
}, CLIENT_TIMEOUT);
|
||||
});
|
||||
});
|
||||
return server;
|
||||
}
|
||||
|
||||
function next() {
|
||||
if (Array.isArray(process._events.exit))
|
||||
process._events.exit = process._events.exit[1];
|
||||
if (++t === tests.length)
|
||||
return;
|
||||
|
||||
var v = tests[t];
|
||||
v.run.call(v);
|
||||
}
|
||||
|
||||
function makeMsg(what, msg) {
|
||||
return '[' + group + what + ']: ' + msg;
|
||||
}
|
||||
|
||||
process.once('uncaughtException', function(err) {
|
||||
if (t > -1 && !/(?:^|\n)AssertionError: /i.test(''+err))
|
||||
console.log(makeMsg(tests[t].what, 'Unexpected Exception:'));
|
||||
throw err;
|
||||
});
|
||||
process.once('exit', function() {
|
||||
assert(t === tests.length,
|
||||
makeMsg('_exit',
|
||||
'Only finished ' + t + '/' + tests.length + ' tests'));
|
||||
});
|
||||
|
||||
|
||||
// Get OpenSSH client version first
|
||||
exec('ssh -V', function(err, stdout, stderr) {
|
||||
if (err) {
|
||||
console.log('OpenSSH client is required for these tests');
|
||||
process.exitCode = 5;
|
||||
return;
|
||||
}
|
||||
var re = /^OpenSSH_([\d\.]+)/;
|
||||
var m = re.exec(stdout.toString());
|
||||
if (!m || !m[1]) {
|
||||
m = re.exec(stderr.toString());
|
||||
if (!m || !m[1]) {
|
||||
console.log('OpenSSH client is required for these tests');
|
||||
process.exitCode = 5;
|
||||
return;
|
||||
}
|
||||
}
|
||||
opensshVer = m[1];
|
||||
next();
|
||||
});
|
||||
22
build/node_modules/ssh2/test/test.js
generated
vendored
Normal file
22
build/node_modules/ssh2/test/test.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
var spawn = require('child_process').spawn,
|
||||
join = require('path').join;
|
||||
|
||||
var files = require('fs').readdirSync(__dirname).filter(function(f) {
|
||||
return (f.substr(0, 5) === 'test-');
|
||||
}).map(function(f) {
|
||||
return join(__dirname, f);
|
||||
}),
|
||||
f = -1;
|
||||
|
||||
function next() {
|
||||
if (++f < files.length) {
|
||||
spawn(process.argv[0], [ files[f] ], { stdio: 'inherit' })
|
||||
.on('exit', function(code) {
|
||||
if (code === 0)
|
||||
process.nextTick(next);
|
||||
else
|
||||
process.exit(code);
|
||||
});
|
||||
}
|
||||
}
|
||||
next();
|
||||
2
build/node_modules/ssh2/util/build_pagent.bat
generated
vendored
Normal file
2
build/node_modules/ssh2/util/build_pagent.bat
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
@cl /Ox pagent.c User32.lib
|
||||
@del /Q *.obj
|
||||
88
build/node_modules/ssh2/util/pagent.c
generated
vendored
Normal file
88
build/node_modules/ssh2/util/pagent.c
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define AGENT_COPYDATA_ID 0x804e50ba
|
||||
#define AGENT_MAX_MSGLEN 8192
|
||||
|
||||
#define GET_32BIT_MSB_FIRST(cp) \
|
||||
(((unsigned long)(unsigned char)(cp)[0] << 24) | \
|
||||
((unsigned long)(unsigned char)(cp)[1] << 16) | \
|
||||
((unsigned long)(unsigned char)(cp)[2] << 8) | \
|
||||
((unsigned long)(unsigned char)(cp)[3]))
|
||||
|
||||
#define GET_32BIT(cp) GET_32BIT_MSB_FIRST(cp)
|
||||
|
||||
#define RET_ERR_BADARGS 10
|
||||
#define RET_ERR_UNAVAILABLE 11
|
||||
#define RET_ERR_NOMAP 12
|
||||
#define RET_ERR_BINSTDIN 13
|
||||
#define RET_ERR_BINSTDOUT 14
|
||||
#define RET_ERR_BADLEN 15
|
||||
|
||||
#define RET_NORESPONSE 1
|
||||
#define RET_RESPONSE 0
|
||||
|
||||
int main (int argc, const char* argv[]) {
|
||||
HWND hwnd;
|
||||
char *mapname;
|
||||
HANDLE filemap;
|
||||
unsigned char *p, *ret;
|
||||
int id, retlen, inlen, n, rmode, r = RET_NORESPONSE;
|
||||
COPYDATASTRUCT cds;
|
||||
void *in;
|
||||
|
||||
if (argc < 2)
|
||||
return RET_ERR_BADARGS;
|
||||
|
||||
hwnd = FindWindow("Pageant", "Pageant");
|
||||
if (!hwnd)
|
||||
return RET_ERR_UNAVAILABLE;
|
||||
|
||||
rmode = _setmode(_fileno(stdin), _O_BINARY);
|
||||
if (rmode == -1)
|
||||
return RET_ERR_BINSTDIN;
|
||||
|
||||
rmode = _setmode(_fileno(stdout), _O_BINARY);
|
||||
if (rmode == -1)
|
||||
return RET_ERR_BINSTDOUT;
|
||||
|
||||
inlen = atoi(argv[1]);
|
||||
in = malloc(inlen);
|
||||
n = fread(in, 1, inlen, stdin);
|
||||
if (n != inlen) {
|
||||
free(in);
|
||||
return RET_ERR_BADLEN;
|
||||
}
|
||||
|
||||
mapname = malloc(32);
|
||||
n = sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId());
|
||||
|
||||
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
|
||||
0, AGENT_MAX_MSGLEN, mapname);
|
||||
if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) {
|
||||
free(in);
|
||||
free(mapname);
|
||||
return RET_ERR_NOMAP;
|
||||
}
|
||||
|
||||
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
|
||||
memcpy(p, in, inlen);
|
||||
cds.dwData = AGENT_COPYDATA_ID;
|
||||
cds.cbData = 1 + n;
|
||||
cds.lpData = mapname;
|
||||
|
||||
id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
|
||||
if (id > 0) {
|
||||
r = RET_RESPONSE;
|
||||
retlen = 4 + GET_32BIT(p);
|
||||
fwrite(p, 1, retlen, stdout);
|
||||
}
|
||||
|
||||
free(in);
|
||||
free(mapname);
|
||||
UnmapViewOfFile(p);
|
||||
CloseHandle(filemap);
|
||||
|
||||
return r;
|
||||
}
|
||||
BIN
build/node_modules/ssh2/util/pagent.exe
generated
vendored
Normal file
BIN
build/node_modules/ssh2/util/pagent.exe
generated
vendored
Normal file
Binary file not shown.
Reference in New Issue
Block a user