ssh2shell 1.9.8 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/lib/ssh2shell.js +163 -129
- package/package.json +57 -57
- package/src/ssh2shell.coffee +151 -128
- package/test/Multiple primary hosts.js +4 -10
- package/test/devtest.js +5 -3
- package/test/issue69.js +24 -24
- package/test/keyboard-interactivetest.js +3 -20
- package/test/lots of commands.js +87 -0
- package/test/notificationstest.js +13 -10
- package/test/sshUserCommandsPosition.js +26 -0
- package/test/sudo no pass test.js +40 -0
- package/test/timeouttest.js +19 -63
- package/test/tunneltest.js +2 -2
- package/test/tunneltestSshUserCommands.js +71 -0
package/README.md
CHANGED
|
@@ -139,8 +139,7 @@ host = {
|
|
|
139
139
|
commands: ["cd /var/logs", "ls -al", "msg:Listed dir", "cd /home/user"],
|
|
140
140
|
|
|
141
141
|
//Optional: Used by this.emit("msg", "my message") to output a message
|
|
142
|
-
msg: {
|
|
143
|
-
send: function( message ) {
|
|
142
|
+
msg: function( message ) {
|
|
144
143
|
console.log(message);
|
|
145
144
|
}
|
|
146
145
|
},
|
package/lib/ssh2shell.js
CHANGED
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
|
|
19
19
|
SSH2Shell.prototype.command = "";
|
|
20
20
|
|
|
21
|
-
SSH2Shell.prototype.
|
|
21
|
+
SSH2Shell.prototype._hosts = [];
|
|
22
|
+
|
|
23
|
+
SSH2Shell.prototype._sshToNextHost = false;
|
|
22
24
|
|
|
23
25
|
SSH2Shell.prototype._primaryhostSessionText = "";
|
|
24
26
|
|
|
@@ -61,7 +63,7 @@
|
|
|
61
63
|
}
|
|
62
64
|
this.idleTimer = setTimeout((function(_this) {
|
|
63
65
|
return function() {
|
|
64
|
-
return _this.emit('commandTimeout', _this.command, _this._buffer, _this._stream, _this.
|
|
66
|
+
return _this.emit('commandTimeout', _this.command, _this._buffer, _this._stream, _this.connection);
|
|
65
67
|
};
|
|
66
68
|
})(this), this.idleTime);
|
|
67
69
|
} else if (this.command.length < 1 && !this.standardPrompt.test(this._buffer)) {
|
|
@@ -76,15 +78,9 @@
|
|
|
76
78
|
clearTimeout(_this.idleTimer);
|
|
77
79
|
}
|
|
78
80
|
if (!_this.sshObj.disableColorFilter) {
|
|
79
|
-
if (_this.sshObj.verbose && _this.sshObj.debug) {
|
|
80
|
-
_this.emit('msg', (_this.sshObj.server.host + ": text formatting filter: ") + _this.sshObj.textColorFilter + ", filtered: " + _this.textColorFilter.test(_this._buffer));
|
|
81
|
-
}
|
|
82
81
|
_this._buffer = _this._buffer.replace(_this.textColorFilter, "");
|
|
83
82
|
}
|
|
84
83
|
if (!_this.sshObj.disableASCIIFilter) {
|
|
85
|
-
if (_this.sshObj.verbose && _this.sshObj.debug) {
|
|
86
|
-
_this.emit('msg', (_this.sshObj.server.host + ": Non-standard ASCII filtered: ") + _this.asciiFilter.test(_this._buffer));
|
|
87
|
-
}
|
|
88
84
|
_this._buffer = _this._buffer.replace(_this.asciiFilter, "");
|
|
89
85
|
}
|
|
90
86
|
switch (true) {
|
|
@@ -93,7 +89,7 @@
|
|
|
93
89
|
_this.emit('msg', _this.sshObj.server.host + ": Sudo command data");
|
|
94
90
|
}
|
|
95
91
|
return _this._processPasswordPrompt();
|
|
96
|
-
case _this.command.length > 0 && _this.command.indexOf("ssh ")
|
|
92
|
+
case _this.sshObj.sshToNextHost && _this.command.length > 0 && _this.command.indexOf("ssh ") === 0:
|
|
97
93
|
if (_this.sshObj.debug) {
|
|
98
94
|
_this.emit('msg', _this.sshObj.server.host + ": SSH command data");
|
|
99
95
|
}
|
|
@@ -117,7 +113,7 @@
|
|
|
117
113
|
_this.emit('msg', "Data processing: data received timeout");
|
|
118
114
|
}
|
|
119
115
|
return _this.idleTimer = setTimeout(function() {
|
|
120
|
-
return _this.emit('commandTimeout', _this.command, _this._buffer, _this._stream, _this.
|
|
116
|
+
return _this.emit('commandTimeout', _this.command, _this._buffer, _this._stream, _this.connection);
|
|
121
117
|
}, _this.idleTime);
|
|
122
118
|
}
|
|
123
119
|
};
|
|
@@ -133,66 +129,74 @@
|
|
|
133
129
|
response = this._sanitizeResponse().trim();
|
|
134
130
|
passwordPrompt = this.passwordPrompt.test(response);
|
|
135
131
|
standardPrompt = this.standardPrompt.test(response);
|
|
136
|
-
if (this.sshObj.verbose) {
|
|
137
|
-
this.emit('msg', this.sshObj.server.host + ": Password previously sent: " + this.sshObj.pwSent);
|
|
138
|
-
}
|
|
139
132
|
if (this.sshObj.debug) {
|
|
140
|
-
this.emit('msg', this.sshObj.server.host + ": Password prompt
|
|
133
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo Password prompt detected: " + passwordPrompt);
|
|
141
134
|
}
|
|
142
|
-
if (this.sshObj.
|
|
143
|
-
this.emit('msg', this.sshObj.server.host + ":
|
|
135
|
+
if (this.sshObj.debug) {
|
|
136
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo Password prompt: Password sent: " + this.sshObj.pwSent);
|
|
144
137
|
}
|
|
145
|
-
if (this.sshObj.
|
|
146
|
-
this.emit('msg', this.sshObj.server.host + ": Sudo Password
|
|
138
|
+
if (this.sshObj.debug) {
|
|
139
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo Password: " + this.sshObj.server.password);
|
|
147
140
|
}
|
|
148
141
|
if (this.sshObj.verbose) {
|
|
149
|
-
this.emit('msg', this.sshObj.server.host + ": Sudo
|
|
142
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo Response: " + response);
|
|
150
143
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (passwordPrompt) {
|
|
144
|
+
switch (true) {
|
|
145
|
+
case passwordPrompt && !this.sshObj.server.password:
|
|
146
|
+
if (this.sshObj.debug) {
|
|
147
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo password prompt no password set");
|
|
148
|
+
}
|
|
149
|
+
return this._resetFromSudoError();
|
|
150
|
+
case passwordPrompt && !this.sshObj.pwSent:
|
|
159
151
|
if (this.sshObj.verbose) {
|
|
160
|
-
this.emit('msg', this.sshObj.server.host + ":
|
|
152
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo password prompt: Buffer: " + response);
|
|
161
153
|
}
|
|
162
154
|
if (this.sshObj.debug) {
|
|
163
|
-
this.emit('msg', this.sshObj.server.host + ":
|
|
155
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo password prompt: Send password ");
|
|
164
156
|
}
|
|
165
157
|
if (this.sshObj.verbose) {
|
|
166
|
-
this.emit('msg', this.sshObj.server.host + ":
|
|
158
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo sent password: " + this.sshObj.server.password);
|
|
167
159
|
}
|
|
168
160
|
this.sshObj.pwSent = true;
|
|
169
161
|
return this._runCommand("" + this.sshObj.server.password);
|
|
170
|
-
|
|
162
|
+
case passwordPrompt && this.sshObj.pwSent:
|
|
163
|
+
if (this.sshObj.verbose) {
|
|
164
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo password faied: response: " + response);
|
|
165
|
+
}
|
|
166
|
+
if (this.sshObj.debug) {
|
|
167
|
+
this.emit('error', this.sshObj.server.host + ": Sudo password was incorrect for " + this.sshObj.server.userName + ", Sudo authentication");
|
|
168
|
+
}
|
|
169
|
+
if (this.sshObj.debug) {
|
|
170
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo failed password prompt: Password: [" + this.sshObj.server.password + "]");
|
|
171
|
+
}
|
|
172
|
+
this.sshObj.pwSent = false;
|
|
173
|
+
return this._resetFromSudoError();
|
|
174
|
+
case standardPrompt:
|
|
171
175
|
if (this.sshObj.debug) {
|
|
172
|
-
this.emit('msg', this.sshObj.server.host + ":
|
|
176
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo password accepted");
|
|
173
177
|
}
|
|
178
|
+
this.sshObj.pwSent = false;
|
|
174
179
|
if (this.sshObj.verbose) {
|
|
175
|
-
this.emit('msg', this.sshObj.server.host + ":
|
|
180
|
+
this.emit('msg', this.sshObj.server.host + ": Sudo Standard Response: " + response);
|
|
176
181
|
}
|
|
177
|
-
return this.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
this.emit('error', this.sshObj.server.host + ": Sudo password was incorrect for " + this.sshObj.server.userName, "Sudo authentication");
|
|
185
|
-
}
|
|
186
|
-
if (this.sshObj.debug) {
|
|
187
|
-
this.emit('msg', this.sshObj.server.host + ": Failed password prompt: Password: [" + this.sshObj.server.password + "]");
|
|
188
|
-
}
|
|
189
|
-
this.sshObj.sessionText += "" + this._buffer;
|
|
190
|
-
this._buffer = "";
|
|
191
|
-
this.command = "";
|
|
192
|
-
return this._stream.write('\x03');
|
|
182
|
+
return this._commandComplete();
|
|
183
|
+
default:
|
|
184
|
+
return this.idleTimer = setTimeout((function(_this) {
|
|
185
|
+
return function() {
|
|
186
|
+
return _this.emit('commandTimeout', _this.command, response, _this._stream, _this._connection);
|
|
187
|
+
};
|
|
188
|
+
})(this), this.idleTime);
|
|
193
189
|
}
|
|
194
190
|
};
|
|
195
191
|
|
|
192
|
+
SSH2Shell.prototype._resetFromSudoError = function() {
|
|
193
|
+
this.sshObj.pwSent = false;
|
|
194
|
+
this.sshObj.sessionText += "" + this._buffer;
|
|
195
|
+
this._buffer = "";
|
|
196
|
+
this.command = "";
|
|
197
|
+
return this._stream.write('\x03');
|
|
198
|
+
};
|
|
199
|
+
|
|
196
200
|
SSH2Shell.prototype._processSSHPrompt = function() {
|
|
197
201
|
var passphrasePrompt, passwordPrompt, response, standardPrompt, using;
|
|
198
202
|
response = this._sanitizeResponse().trim();
|
|
@@ -225,22 +229,25 @@
|
|
|
225
229
|
return this._runCommand("" + this.sshObj.server.passPhrase);
|
|
226
230
|
} else if (standardPrompt) {
|
|
227
231
|
if (this.sshObj.debug) {
|
|
228
|
-
this.emit('msg', this.sshObj.server.host + ": SSH
|
|
232
|
+
this.emit('msg', this.sshObj.server.host + ": SSH standard prompt: connection failed");
|
|
229
233
|
}
|
|
230
234
|
this.emit('msg', this.sshObj.server.host + ": SSH connection failed");
|
|
231
235
|
this.emit('msg', this.sshObj.server.host + ": SSH failed response: " + response);
|
|
232
236
|
this.sshObj.sessionText += this.sshObj.server.host + ": SSH failed: response: " + response;
|
|
233
237
|
return this._runExit();
|
|
234
238
|
} else {
|
|
235
|
-
this.emit('msg', this.sshObj.server.host + ": SSH
|
|
236
|
-
if (this.sshObj.verbose
|
|
237
|
-
this.emit('msg', this.sshObj.server.host + ":
|
|
239
|
+
this.emit('msg', this.sshObj.server.host + ": SSH no prompt was not detected");
|
|
240
|
+
if (this.sshObj.verbose) {
|
|
241
|
+
this.emit('msg', this.sshObj.server.host + ": SSH response: " + response);
|
|
242
|
+
}
|
|
243
|
+
if (this.sshObj.verbose && !this.sshObj.server.hasOwnProperty("password")) {
|
|
244
|
+
this.emit('msg', this.sshObj.server.host + ": SSH password prompt: " + this.sshObj.passwordPrompt);
|
|
238
245
|
}
|
|
239
246
|
if (this.sshObj.verbose && this.sshObj.server.hasOwnProperty("passPhrase")) {
|
|
240
|
-
this.emit('msg', this.sshObj.server.host + ":
|
|
247
|
+
this.emit('msg', this.sshObj.server.host + ": SSH passphrase prompt: " + this.sshObj.passphrasePrompt);
|
|
241
248
|
}
|
|
242
249
|
if (this.sshObj.verbose) {
|
|
243
|
-
this.emit('msg', this.sshObj.server.host + ":
|
|
250
|
+
this.emit('msg', this.sshObj.server.host + ": SSH standard prompt: " + this.sshObj.standardPrompt);
|
|
244
251
|
}
|
|
245
252
|
return this._runExit();
|
|
246
253
|
}
|
|
@@ -252,9 +259,16 @@
|
|
|
252
259
|
if (this.sshObj.debug) {
|
|
253
260
|
this.emit('msg', this.sshObj.server.host + ": SSH complete: normal prompt");
|
|
254
261
|
}
|
|
262
|
+
if (this.sshObj.showBanner) {
|
|
263
|
+
this.sshObj.sessionText += "\n " + response;
|
|
264
|
+
}
|
|
255
265
|
this.sshObj.exitCommands.push("exit");
|
|
256
266
|
this.emit('msg', "" + this.sshObj.connectedMessage);
|
|
257
267
|
this.emit('msg', "" + this.sshObj.readyMessage);
|
|
268
|
+
if (this.sshObj.debug) {
|
|
269
|
+
this.emit('msg', this.sshObj.server.host + ": SSH complete: next command");
|
|
270
|
+
}
|
|
271
|
+
this.sshObj.sshToNextHost = false;
|
|
258
272
|
return this._nextCommand();
|
|
259
273
|
} else if (passwordPrompt || passphrasePrompt) {
|
|
260
274
|
this.emit('msg', this.sshObj.server.host + ": SSH authentication failed");
|
|
@@ -268,9 +282,9 @@
|
|
|
268
282
|
using = (function() {
|
|
269
283
|
switch (false) {
|
|
270
284
|
case !passwordPrompt:
|
|
271
|
-
return "password: " + this.sshObj.server.password;
|
|
285
|
+
return "SSH password: " + this.sshObj.server.password;
|
|
272
286
|
case !passphrasePrompt:
|
|
273
|
-
return "passphrase: " + this.sshObj.server.passPhrase;
|
|
287
|
+
return "SSH passphrase: " + this.sshObj.server.passPhrase;
|
|
274
288
|
}
|
|
275
289
|
}).call(this);
|
|
276
290
|
this.emit('error', this.sshObj.server.host + ": SSH authentication failed for " + this.sshObj.server.userName + "@" + this.sshObj.server.host, "Nested host authentication");
|
|
@@ -278,7 +292,7 @@
|
|
|
278
292
|
this.emit('msg', (this.sshObj.server.host + ": SSH auth failed: Using ") + using);
|
|
279
293
|
}
|
|
280
294
|
if (this.sshObj.verbose) {
|
|
281
|
-
this.emit('msg', this.sshObj.server.host + ": SSH
|
|
295
|
+
this.emit('msg', this.sshObj.server.host + ": SSH response: " + response);
|
|
282
296
|
}
|
|
283
297
|
if (this._connections.length > 0) {
|
|
284
298
|
return this._previousHost();
|
|
@@ -322,7 +336,7 @@
|
|
|
322
336
|
SSH2Shell.prototype._commandComplete = function() {
|
|
323
337
|
var response;
|
|
324
338
|
response = this._buffer.trim();
|
|
325
|
-
if (this.command !== "" && this.command !== "exit" && this.
|
|
339
|
+
if (this.command !== "" && this.command !== "exit" && this.sshObj.sshToNextHost !== true) {
|
|
326
340
|
if (this.sshObj.verbose) {
|
|
327
341
|
this.emit('msg', this.sshObj.server.host + ": Command complete:\nCommand:\n " + this.command + "\nResponse: " + response);
|
|
328
342
|
}
|
|
@@ -388,7 +402,7 @@
|
|
|
388
402
|
if (this.sshObj.debug) {
|
|
389
403
|
this.emit('msg', this.sshObj.server.host + ": Reload previous host");
|
|
390
404
|
}
|
|
391
|
-
return this.
|
|
405
|
+
return this._runExit();
|
|
392
406
|
} else {
|
|
393
407
|
return this._runExit();
|
|
394
408
|
}
|
|
@@ -403,24 +417,32 @@
|
|
|
403
417
|
if (this.sshObj.debug) {
|
|
404
418
|
this.emit('msg', this.sshObj.server.host + ": Clearing previous event handlers");
|
|
405
419
|
}
|
|
420
|
+
if (this.sshObj.debug) {
|
|
421
|
+
this.emit('msg', this.sshObj.server.host + ": Remove previous event handlers");
|
|
422
|
+
}
|
|
423
|
+
this._removeEvents();
|
|
406
424
|
this._connections.push(this.sshObj);
|
|
407
425
|
this.sshObj = nextHost;
|
|
408
426
|
return this._initiate(this._sshConnect);
|
|
409
427
|
};
|
|
410
428
|
|
|
411
|
-
SSH2Shell.prototype._nextPrimaryHost = function(
|
|
412
|
-
if (
|
|
429
|
+
SSH2Shell.prototype._nextPrimaryHost = function(connect) {
|
|
430
|
+
if (this._hosts.length > 0) {
|
|
413
431
|
if (this.sshObj.server) {
|
|
414
432
|
if (this.sshObj.debug) {
|
|
415
433
|
this.emit('msg', this.sshObj.server.host + ": Current primary host");
|
|
416
434
|
}
|
|
435
|
+
if (this.sshObj.debug) {
|
|
436
|
+
this.emit('msg', this.sshObj.server.host + ": Remove previous event handlers");
|
|
437
|
+
}
|
|
438
|
+
this._removeEvents();
|
|
417
439
|
}
|
|
418
|
-
this.sshObj = this.
|
|
440
|
+
this.sshObj = this._hosts.shift();
|
|
419
441
|
this._primaryhostSessionText = this.sshObj.server.host + ": ";
|
|
420
442
|
if (this.sshObj.debug) {
|
|
421
443
|
this.emit('msg', this.sshObj.server.host + ": Next primary host");
|
|
422
444
|
}
|
|
423
|
-
return this._initiate(
|
|
445
|
+
return this._initiate(connect);
|
|
424
446
|
} else {
|
|
425
447
|
if (this.sshObj.debug) {
|
|
426
448
|
this.emit('msg', this.sshObj.server.host + ": No more primary hosts");
|
|
@@ -479,6 +501,7 @@
|
|
|
479
501
|
sshOptions += ' -o "StrictHostKeyChecking=no"';
|
|
480
502
|
sshOptions += " -p " + this.sshObj.server.port;
|
|
481
503
|
this.sshObj.sshAuth = false;
|
|
504
|
+
this.sshObj.sshToNextHost = true;
|
|
482
505
|
this.command = "ssh " + sshFlags + " " + sshOptions + " " + this.sshObj.server.userName + "@" + this.sshObj.server.host;
|
|
483
506
|
if (this.sshObj.debug) {
|
|
484
507
|
this.emit('msg', this.sshObj.server.host + ": SSH command: connect");
|
|
@@ -496,6 +519,9 @@
|
|
|
496
519
|
}
|
|
497
520
|
this.command = this.sshObj.exitCommands.pop();
|
|
498
521
|
if (this._connections && this._connections.length > 0) {
|
|
522
|
+
if (this.sshObj.verbose) {
|
|
523
|
+
this.emit('msg', this.sshObj.server.host + ": Primary host: " + this._connections[0].server.host);
|
|
524
|
+
}
|
|
499
525
|
this._connections[0].sessionText += "\n" + this.sshObj.server.host + ": " + this.sshObj.sessionText;
|
|
500
526
|
}
|
|
501
527
|
return this._runCommand(this.command);
|
|
@@ -528,18 +554,29 @@
|
|
|
528
554
|
};
|
|
529
555
|
|
|
530
556
|
SSH2Shell.prototype._removeEvents = function() {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
557
|
+
|
|
558
|
+
/*
|
|
559
|
+
if @sshObj.debug
|
|
560
|
+
@.emit 'msg', "#{@sshObj.server.host}: Event handler count:"
|
|
561
|
+
@.emit 'msg', "keyboard-interactive: " + (@.listenerCount 'keyboard-interactive')
|
|
562
|
+
@.emit 'msg', "error: " + (@.listenerCount "error")
|
|
563
|
+
@.emit 'msg', "data: " + (@.listenerCount "data")
|
|
564
|
+
@.emit 'msg', "stderrData: " + (@.listenerCount "stderrData")
|
|
565
|
+
@.emit 'msg', "end: " + (@.listenerCount 'end')
|
|
566
|
+
@.emit 'msg', "commandProcessing: " + (@.listenerCount 'commandProcessing')
|
|
567
|
+
@.emit 'msg', "commandComplete: " + (@.listenerCount 'commandComplete')
|
|
568
|
+
@.emit 'msg', "commandTimeout: " + (@.listenerCount 'commandTimeout')
|
|
569
|
+
@.emit 'msg', "msg: " + (@.listenerCount 'msg')
|
|
570
|
+
*/
|
|
536
571
|
if (typeof this.sshObj.onData === 'function') {
|
|
537
572
|
this.removeListener("data", this.sshObj.onData);
|
|
538
573
|
}
|
|
574
|
+
this.removeAllListeners("error");
|
|
539
575
|
if (typeof this.sshObj.onStderrData === 'function') {
|
|
540
576
|
this.removeListener("stderrData", this.sshObj.onStderrData);
|
|
541
577
|
}
|
|
542
578
|
this.removeAllListeners('end');
|
|
579
|
+
this.removeAllListeners('keyboard-interactive');
|
|
543
580
|
this.removeAllListeners('commandProcessing');
|
|
544
581
|
this.removeAllListeners('commandComplete');
|
|
545
582
|
this.removeAllListeners('commandTimeout');
|
|
@@ -570,6 +607,7 @@
|
|
|
570
607
|
this._commandComplete = bind(this._commandComplete, this);
|
|
571
608
|
this._processNotifications = bind(this._processNotifications, this);
|
|
572
609
|
this._processSSHPrompt = bind(this._processSSHPrompt, this);
|
|
610
|
+
this._resetFromSudoError = bind(this._resetFromSudoError, this);
|
|
573
611
|
this._processPasswordPrompt = bind(this._processPasswordPrompt, this);
|
|
574
612
|
this._sanitizeResponse = bind(this._sanitizeResponse, this);
|
|
575
613
|
this._onData = bind(this._onData, this);
|
|
@@ -578,10 +616,11 @@
|
|
|
578
616
|
this.onCommandComplete = bind(this.onCommandComplete, this);
|
|
579
617
|
this.onCommandProcessing = bind(this.onCommandProcessing, this);
|
|
580
618
|
this._callback = bind(this._callback, this);
|
|
581
|
-
|
|
582
|
-
|
|
619
|
+
SSH2Shell.__super__.constructor.call(this, hosts);
|
|
620
|
+
if (typeIsArray(hosts) && hosts.length > 0) {
|
|
621
|
+
this._hosts = hosts;
|
|
583
622
|
} else {
|
|
584
|
-
this.
|
|
623
|
+
this._hosts = [hosts];
|
|
585
624
|
}
|
|
586
625
|
this.ssh2Client = require('ssh2').Client;
|
|
587
626
|
this.on("newPrimmaryHost", this._nextPrimaryHost);
|
|
@@ -595,78 +634,72 @@
|
|
|
595
634
|
return console.error(data);
|
|
596
635
|
};
|
|
597
636
|
})(this));
|
|
598
|
-
this._allSessions = "";
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
SSH2Shell.prototype._initiate = function(callback) {
|
|
602
|
-
this._removeEvents();
|
|
603
|
-
if (typeof this.sshObj.msg === 'function') {
|
|
604
|
-
this.on("msg", this.sshObj.msg.send);
|
|
605
|
-
} else {
|
|
606
|
-
this.on("msg", (function(_this) {
|
|
607
|
-
return function(message) {
|
|
608
|
-
return console.log(message);
|
|
609
|
-
};
|
|
610
|
-
})(this));
|
|
611
|
-
}
|
|
612
|
-
this._loadDefaults();
|
|
613
|
-
if (this.sshObj.debug) {
|
|
614
|
-
this.emit('msg', this.sshObj.server.host + ": initiate");
|
|
615
|
-
}
|
|
616
|
-
this.on("keyboard-interactive", (function(_this) {
|
|
617
|
-
return function(name, instructions, instructionsLang, prompts, finish) {
|
|
618
|
-
var str;
|
|
619
|
-
if (_this.sshObj.debug) {
|
|
620
|
-
_this.emit('msg', _this.sshObj.server.host + ": Class.keyboard-interactive");
|
|
621
|
-
}
|
|
622
|
-
if (_this.sshObj.verbose) {
|
|
623
|
-
_this.emit('msg', "name: " + name);
|
|
624
|
-
_this.emit('msg', "instructions: " + instructions);
|
|
625
|
-
str = JSON.stringify(prompts, null, 4);
|
|
626
|
-
return _this.emit('msg', "Prompts object: " + str);
|
|
627
|
-
}
|
|
628
|
-
};
|
|
629
|
-
})(this));
|
|
630
637
|
this.on("error", (function(_this) {
|
|
631
638
|
return function(err, type, close, callback) {
|
|
632
639
|
if (close == null) {
|
|
633
640
|
close = false;
|
|
634
641
|
}
|
|
635
642
|
if (_this.sshObj.debug) {
|
|
636
|
-
_this.emit('msg',
|
|
643
|
+
_this.emit('msg', "Class.error: " + err + ", " + type);
|
|
637
644
|
}
|
|
638
645
|
if (err instanceof Error) {
|
|
639
646
|
_this.emit('msg', "Error: " + err.message + ", Level: " + err.level);
|
|
640
647
|
} else {
|
|
641
648
|
_this.emit('msg', (type + " error: ") + err);
|
|
642
649
|
}
|
|
643
|
-
if (typeof callback === 'function') {
|
|
644
|
-
callback(err, type);
|
|
645
|
-
}
|
|
646
650
|
if (close) {
|
|
647
|
-
return _this.
|
|
651
|
+
return _this._stream.close();
|
|
648
652
|
}
|
|
649
653
|
};
|
|
650
654
|
})(this));
|
|
651
|
-
this.
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
655
|
+
if (this._hosts[0].server.tryKeyboard) {
|
|
656
|
+
this.on("keyboard-interactive", (function(_this) {
|
|
657
|
+
return function(name, instructions, instructionsLang, prompts, finish) {
|
|
658
|
+
var str;
|
|
659
|
+
if (_this.sshObj.debug) {
|
|
660
|
+
_this.emit('msg', _this.sshObj.server.host + ": Class.keyboard-interactive");
|
|
661
|
+
}
|
|
662
|
+
if (_this.sshObj.verbose) {
|
|
663
|
+
_this.emit('msg', "name: " + name);
|
|
664
|
+
_this.emit('msg', "instructions: " + instructions);
|
|
665
|
+
str = JSON.stringify(prompts, null, 4);
|
|
666
|
+
return _this.emit('msg', "Prompts object: " + str);
|
|
667
|
+
}
|
|
668
|
+
};
|
|
669
|
+
})(this));
|
|
670
|
+
}
|
|
671
|
+
this._allSessions = "";
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
SSH2Shell.prototype._initiate = function(action) {
|
|
675
|
+
if (this.sshObj.debug) {
|
|
676
|
+
this.emit('msg', this.sshObj.server.host + ": initiate");
|
|
677
|
+
}
|
|
678
|
+
this._loadDefaults();
|
|
679
|
+
if (typeof action === 'function') {
|
|
680
|
+
return action();
|
|
660
681
|
}
|
|
661
682
|
};
|
|
662
683
|
|
|
663
|
-
SSH2Shell.prototype._loadDefaults = function(
|
|
684
|
+
SSH2Shell.prototype._loadDefaults = function() {
|
|
664
685
|
var ref, ref1, ref2, ref3, ref4, ref5, ref6;
|
|
686
|
+
if (this.sshObj.msg && this.sshObj.msg.send && typeof this.sshObj.msg.send === 'function') {
|
|
687
|
+
this.on("msg", this.sshObj.msg.send);
|
|
688
|
+
} else if (this.sshObj.msg && typeof this.sshObj.msg === 'function') {
|
|
689
|
+
this.on("msg", this.sshObj.msg);
|
|
690
|
+
} else {
|
|
691
|
+
this.on("msg", (function(_this) {
|
|
692
|
+
return function(message) {
|
|
693
|
+
return console.log(message);
|
|
694
|
+
};
|
|
695
|
+
})(this));
|
|
696
|
+
}
|
|
665
697
|
if (this.sshObj.debug) {
|
|
666
698
|
this.emit('msg', this.sshObj.server.host + ": Load Defaults");
|
|
667
699
|
}
|
|
668
700
|
this.command = "";
|
|
669
701
|
this._buffer = "";
|
|
702
|
+
this.sshObj.sshToNextHost = false;
|
|
670
703
|
if (!this.sshObj.connectedMessage) {
|
|
671
704
|
this.sshObj.connectedMessage = "Connected";
|
|
672
705
|
}
|
|
@@ -776,10 +809,8 @@
|
|
|
776
809
|
if (_this.sshObj.verbose) {
|
|
777
810
|
_this.emit('msg', _this.sshObj.server.host + ": Timeout command: " + command + " response: " + response);
|
|
778
811
|
}
|
|
779
|
-
_this.
|
|
780
|
-
return _this.
|
|
781
|
-
return _this.sshObj.sessionText += _this._buffer;
|
|
782
|
-
});
|
|
812
|
+
_this.emit("error", _this.sshObj.server.host + ": Command timed out after " + (_this.idleTime / 1000) + " seconds", "Timeout", true, function(err, type) {});
|
|
813
|
+
return _this.sshObj.sessionText += _this._buffer;
|
|
783
814
|
};
|
|
784
815
|
})(this);
|
|
785
816
|
if (typeof this.sshObj.onKeyboardInteractive === 'function') {
|
|
@@ -804,10 +835,7 @@
|
|
|
804
835
|
this.emit('msg', this.sshObj.server.host + ": Host loaded");
|
|
805
836
|
}
|
|
806
837
|
if (this.sshObj.verbose) {
|
|
807
|
-
this.emit('msg', this.sshObj);
|
|
808
|
-
}
|
|
809
|
-
if (typeof callback === 'function') {
|
|
810
|
-
return callback();
|
|
838
|
+
return this.emit('msg', this.sshObj);
|
|
811
839
|
}
|
|
812
840
|
};
|
|
813
841
|
|
|
@@ -884,7 +912,7 @@
|
|
|
884
912
|
}
|
|
885
913
|
_this._primaryhostSessionText += _this.sshObj.sessionText + "\n";
|
|
886
914
|
_this._allSessions += _this._primaryhostSessionText;
|
|
887
|
-
if (
|
|
915
|
+
if (_this._hosts.length === 0) {
|
|
888
916
|
_this.emit('end', _this._allSessions, _this.sshObj);
|
|
889
917
|
}
|
|
890
918
|
return _this._removeEvents();
|
|
@@ -911,12 +939,18 @@
|
|
|
911
939
|
if (_this.sshObj.debug) {
|
|
912
940
|
_this.emit('msg', _this.sshObj.server.host + ": Connection.close");
|
|
913
941
|
}
|
|
942
|
+
if (_this.idleTimer) {
|
|
943
|
+
clearTimeout(_this.idleTimer);
|
|
944
|
+
}
|
|
945
|
+
if (_this.dataReceivedTimer) {
|
|
946
|
+
clearTimeout(_this.dataReceivedTimer);
|
|
947
|
+
}
|
|
914
948
|
if (had_error) {
|
|
915
949
|
_this.emit("error", had_error, "Connection close");
|
|
916
950
|
} else {
|
|
917
951
|
_this.emit('msg', _this.sshObj.closedMessage);
|
|
918
952
|
}
|
|
919
|
-
if (
|
|
953
|
+
if (_this._hosts.length === 0) {
|
|
920
954
|
if (typeof _this._callback === 'function') {
|
|
921
955
|
return _this._callback(_this._allSessions);
|
|
922
956
|
}
|
package/package.json
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "ssh2shell",
|
|
3
|
-
"version": "
|
|
4
|
-
"author": "cmp-202",
|
|
5
|
-
"description": "A wrapper class for ssh2 to run multiple sequential commands in an SSH shell session, handle command responses, and tunnel through to other hosts using nested host objects",
|
|
6
|
-
"main": "./lib/ssh2shell.js",
|
|
7
|
-
"engines": {
|
|
8
|
-
"node": ">=4.5.0"
|
|
9
|
-
},
|
|
10
|
-
"dependencies": {
|
|
11
|
-
"ssh2": "^1.4.0"
|
|
12
|
-
},
|
|
13
|
-
"devDependencies": {
|
|
14
|
-
"coffee-script": "^1.12.7",
|
|
15
|
-
"dotenv": "^8.6.0"
|
|
16
|
-
},
|
|
17
|
-
"scripts": {},
|
|
18
|
-
"keywords": [
|
|
19
|
-
"SSH",
|
|
20
|
-
"ssh2",
|
|
21
|
-
"shell",
|
|
22
|
-
"server",
|
|
23
|
-
"client",
|
|
24
|
-
"multiple",
|
|
25
|
-
"command",
|
|
26
|
-
"commands",
|
|
27
|
-
"tunnel",
|
|
28
|
-
"deploy",
|
|
29
|
-
"host",
|
|
30
|
-
"hosts",
|
|
31
|
-
"automation",
|
|
32
|
-
"fingerprint",
|
|
33
|
-
"validation",
|
|
34
|
-
"hash",
|
|
35
|
-
"cipher",
|
|
36
|
-
"persistent",
|
|
37
|
-
"sequential",
|
|
38
|
-
"console",
|
|
39
|
-
"sudo",
|
|
40
|
-
"su",
|
|
41
|
-
"prompt",
|
|
42
|
-
"session",
|
|
43
|
-
"connection"
|
|
44
|
-
],
|
|
45
|
-
"repository": {
|
|
46
|
-
"type": "git",
|
|
47
|
-
"url": "http://github.com/cmp-202/ssh2shell"
|
|
48
|
-
},
|
|
49
|
-
"bugs": {
|
|
50
|
-
"url": "https://github.com/cmp-202/ssh2shell/issues"
|
|
51
|
-
},
|
|
52
|
-
"homepage": "https://github.com/cmp-202/ssh2shell/wiki",
|
|
53
|
-
"directories": {
|
|
54
|
-
"test": "test"
|
|
55
|
-
},
|
|
56
|
-
"license": "ISC"
|
|
57
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "ssh2shell",
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"author": "cmp-202",
|
|
5
|
+
"description": "A wrapper class for ssh2 to run multiple sequential commands in an SSH shell session, handle command responses, and tunnel through to other hosts using nested host objects",
|
|
6
|
+
"main": "./lib/ssh2shell.js",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=4.5.0"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"ssh2": "^1.4.0"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"coffee-script": "^1.12.7",
|
|
15
|
+
"dotenv": "^8.6.0"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"SSH",
|
|
20
|
+
"ssh2",
|
|
21
|
+
"shell",
|
|
22
|
+
"server",
|
|
23
|
+
"client",
|
|
24
|
+
"multiple",
|
|
25
|
+
"command",
|
|
26
|
+
"commands",
|
|
27
|
+
"tunnel",
|
|
28
|
+
"deploy",
|
|
29
|
+
"host",
|
|
30
|
+
"hosts",
|
|
31
|
+
"automation",
|
|
32
|
+
"fingerprint",
|
|
33
|
+
"validation",
|
|
34
|
+
"hash",
|
|
35
|
+
"cipher",
|
|
36
|
+
"persistent",
|
|
37
|
+
"sequential",
|
|
38
|
+
"console",
|
|
39
|
+
"sudo",
|
|
40
|
+
"su",
|
|
41
|
+
"prompt",
|
|
42
|
+
"session",
|
|
43
|
+
"connection"
|
|
44
|
+
],
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "http://github.com/cmp-202/ssh2shell"
|
|
48
|
+
},
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/cmp-202/ssh2shell/issues"
|
|
51
|
+
},
|
|
52
|
+
"homepage": "https://github.com/cmp-202/ssh2shell/wiki",
|
|
53
|
+
"directories": {
|
|
54
|
+
"test": "test"
|
|
55
|
+
},
|
|
56
|
+
"license": "ISC"
|
|
57
|
+
}
|