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

telnet-client

Package Overview
Dependencies
Maintainers
1
Versions
108
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

telnet-client - npm Package Compare versions

Comparing version 0.2.2 to 0.3.0

examples/ready.js

288

lib/telnet-client.js
// Node.js Telnet client
// TODO: * login (username/password)
// * raise and emit errors
var util = require('util');
var events = require('events');
var net = require('net');
var socket = new net.Socket();
var events = require('events')
var net = require('net')
var Promise = require('bluebird')
var socket = new net.Socket()
var util = require('util')

@@ -13,177 +12,199 @@

function Telnet() {
events.EventEmitter.call(this);
if (false === (this instanceof Telnet)) return new Telnet();
events.EventEmitter.call(this)
if (false === (this instanceof Telnet)) return new Telnet()
}
util.inherits(Telnet, events.EventEmitter);
util.inherits(Telnet, events.EventEmitter)
Telnet.prototype.connect = function(opts) {
var self = this;
var host = (typeof opts.host !== 'undefined' ? opts.host : '127.0.0.1');
var port = (typeof opts.port !== 'undefined' ? opts.port : 23);
this.timeout = (typeof opts.timeout !== 'undefined' ? opts.timeout : 500);
this.shellPrompt = (typeof opts.shellPrompt !== 'undefined'
? opts.shellPrompt : /(?:\/ )?#\s/);
this.loginPrompt = (typeof opts.loginPrompt !== 'undefined'
? opts.loginPrompt : /login[: ]*$/i);
this.passwordPrompt = (typeof opts.passwordPrompt !== 'undefined'
? opts.passwordPrompt : /Password: /i);
this.failedLoginPrompt = (typeof opts.failedLoginPrompt !== 'undefined'
? opts.failedLoginPrompt : undefined);
this.username = (typeof opts.username !== 'undefined' ? opts.username : 'root');
this.password = (typeof opts.password !== 'undefined' ? opts.password : 'guest');
this.irs = (typeof opts.irs !== 'undefined' ? opts.irs : '\r\n');
this.ors = (typeof opts.ors !== 'undefined' ? opts.ors : '\n');
this.echoLines = (typeof opts.echoLines !== 'undefined' ? opts.echoLines : 1);
this.pageSeparator = (typeof opts.pageSeparator !== 'undefined'
? opts.pageSeparator : '---- More');
this.response = '';
this.telnetState;
var self = this
this.telnetSocket = net.createConnection({
port: port,
host: host
}, function() {
self.telnetState = 'start';
self.stringData = '';
self.emit('connect');
});
return new Promise(function(resolve, reject) {
var host = (typeof opts.host !== 'undefined' ? opts.host : '127.0.0.1')
var port = (typeof opts.port !== 'undefined' ? opts.port : 23)
self.timeout = (typeof opts.timeout !== 'undefined' ? opts.timeout : 500)
self.shellPrompt = (typeof opts.shellPrompt !== 'undefined'
? opts.shellPrompt : /(?:\/ )?#\s/)
self.loginPrompt = (typeof opts.loginPrompt !== 'undefined'
? opts.loginPrompt : /login[: ]*$/i)
self.passwordPrompt = (typeof opts.passwordPrompt !== 'undefined'
? opts.passwordPrompt : /Password: /i)
self.failedLoginPrompt = (typeof opts.failedLoginPrompt !== 'undefined'
? opts.failedLoginPrompt : undefined)
self.username = (typeof opts.username !== 'undefined' ? opts.username : 'root')
self.password = (typeof opts.password !== 'undefined' ? opts.password : 'guest')
self.irs = (typeof opts.irs !== 'undefined' ? opts.irs : '\r\n')
self.ors = (typeof opts.ors !== 'undefined' ? opts.ors : '\n')
self.echoLines = (typeof opts.echoLines !== 'undefined' ? opts.echoLines : 1)
self.pageSeparator = (typeof opts.pageSeparator !== 'undefined'
? opts.pageSeparator : '---- More')
self.response = ''
self.telnetState
this.telnetSocket.setTimeout(this.timeout, function() {
if (self.telnetSocket._connecting === true) {
// info: cannot connect; emit error and destroy
self.emit('error', 'Cannot connect');
self.telnetSocket = net.createConnection({
port: port,
host: host
}, function() {
self.telnetState = 'start'
self.stringData = ''
self.emit('connect')
})
self.telnetSocket.destroy();
}
else self.emit('timeout');
});
self.telnetSocket.setTimeout(self.timeout, function() {
if (self.telnetSocket._connecting === true) {
// info: if cannot connect, emit error and destroy
self.emit('error', 'Cannot connect')
self.telnetSocket.destroy()
}
else self.emit('timeout')
})
this.telnetSocket.on('data', function(data) {
parseData(data, self);
});
self.telnetSocket.on('data', function(data) {
parseData(data, self, function(event, parsed) {
if (event === 'ready') {
resolve(parsed)
}
})
})
this.telnetSocket.on('error', function(error) {
self.emit('error', error);
});
self.telnetSocket.on('error', function(error) {
self.emit('error', error)
reject(error)
})
this.telnetSocket.on('end', function() {
self.emit('end');
});
self.telnetSocket.on('end', function() {
self.emit('end')
})
this.telnetSocket.on('close', function() {
self.emit('close');
});
self.telnetSocket.on('close', function() {
self.emit('close')
reject('connection closed')
})
})
}
Telnet.prototype.exec = function(cmd, opts, callback) {
var self = this;
cmd += this.ors;
var self = this
cmd += this.ors
if (opts && opts instanceof Function) callback = opts
if (opts && opts instanceof Function) callback = opts;
else if (opts && opts instanceof Object) {
self.shellPrompt = opts.shellPrompt || self.shellPrompt;
self.loginPrompt = opts.loginPrompt || self.loginPrompt;
self.failedLoginPrompt = opts.failedLoginPrompt || self.failedLoginPrompt;
self.timeout = opts.timeout || self.timeout;
self.irs = opts.irs || self.irs;
self.ors = opts.ors || self.ors;
self.echoLines = opts.echoLines || self.echoLines;
}
return new Promise(function(resolve, reject) {
if (opts && opts instanceof Object) {
self.shellPrompt = opts.shellPrompt || self.shellPrompt
self.loginPrompt = opts.loginPrompt || self.loginPrompt
self.failedLoginPrompt = opts.failedLoginPrompt || self.failedLoginPrompt
self.timeout = opts.timeout || self.timeout
self.irs = opts.irs || self.irs
self.ors = opts.ors || self.ors
self.echoLines = opts.echoLines || self.echoLines
}
if (this.telnetSocket.writable) {
this.telnetSocket.write(cmd, function() {
self.telnetState = 'response';
self.emit('writedone');
if (self.telnetSocket.writable) {
self.telnetSocket.write(cmd, function() {
self.telnetState = 'response'
self.emit('writedone')
self.once('responseready', function() {
if (callback && self.cmdOutput !== 'undefined') {
callback(self.cmdOutput.join('\n'));
}
else if (callback && self.cmdOutput === 'undefined') callback;
self.once('responseready', function() {
if (self.cmdOutput !== 'undefined') {
resolve(self.cmdOutput.join('\n'))
}
else reject(new Error('invalid response'))
// reset stored response
self.stringData = '';
});
});
}
// reset stored response
self.stringData = ''
})
})
}
}).asCallback(callback)
}
Telnet.prototype.end = function() {
this.telnetSocket.end();
var self = this
return new Promise(function(resolve) {
self.telnetSocket.end()
resolve()
})
}
Telnet.prototype.destroy = function() {
this.telnetSocket.destroy();
var self = this
return new Promise(function(resolve) {
self.telnetSocket.destroy()
resolve()
})
}
function parseData(chunk, telnetObj) {
var promptIndex = '';
function parseData(chunk, telnetObj, callback) {
var promptIndex = ''
if (chunk[0] === 255 && chunk[1] !== 255) {
telnetObj.stringData = '';
var negReturn = negotiate(telnetObj, chunk);
telnetObj.stringData = ''
var negReturn = negotiate(telnetObj.telnetSocket, chunk)
if (negReturn == undefined) return;
else chunk = negReturn;
if (negReturn == undefined) return
else chunk = negReturn
}
if (telnetObj.telnetState === 'start') {
telnetObj.telnetState = 'getprompt';
telnetObj.telnetState = 'getprompt'
}
if (telnetObj.telnetState === 'getprompt') {
var stringData = chunk.toString();
var promptIndex = stringData.search(regexEscape(telnetObj.shellPrompt));
var stringData = chunk.toString()
var promptIndex = stringData.search(regexEscape(telnetObj.shellPrompt))
if (promptIndex !== -1) {
telnetObj.shellPrompt = stringData.substring(promptIndex);
telnetObj.telnetState = 'sendcmd';
telnetObj.stringData = '';
telnetObj.emit('ready', telnetObj.shellPrompt);
telnetObj.shellPrompt = stringData.substring(promptIndex)
telnetObj.telnetState = 'sendcmd'
telnetObj.stringData = ''
telnetObj.emit('ready', telnetObj.shellPrompt)
if (callback) callback('ready', telnetObj.shellPrompt)
}
else if (stringData.search(regexEscape(telnetObj.loginPrompt)) !== -1) {
telnetObj.telnetState = 'login';
login(telnetObj, 'username');
telnetObj.telnetState = 'login'
login(telnetObj, 'username')
}
else if (stringData.search(regexEscape(telnetObj.passwordPrompt)) !== -1) {
telnetObj.telnetState = 'login';
login(telnetObj, 'password');
telnetObj.telnetState = 'login'
login(telnetObj, 'password')
}
else if (typeof telnetObj.failedLoginPrompt !== 'undefined' && stringData.search(telnetObj.failedLoginPrompt) !== -1) {
telnetObj.telnetState = 'failedlogin';
telnetObj.emit('failedlogin', stringData);
telnetObj.destroy();
telnetObj.telnetState = 'failedlogin'
telnetObj.emit('failedlogin', stringData)
telnetObj.destroy()
}
else return;
else return
}
else if (telnetObj.telnetState === 'response') {
var stringData = chunk.toString();
telnetObj.stringData += stringData;
promptIndex = stringData.search(regexEscape(telnetObj.shellPrompt));
var stringData = chunk.toString()
telnetObj.stringData += stringData
promptIndex = stringData.search(regexEscape(telnetObj.shellPrompt))
if (promptIndex === -1 && stringData.length !== 0) {
if (stringData.search(regexEscape(telnetObj.pageSeparator)) !== -1) {
telnetObj.telnetSocket.write(Buffer('20', 'hex'));
telnetObj.telnetSocket.write(Buffer('20', 'hex'))
}
return;
return
}
telnetObj.cmdOutput = telnetObj.stringData.split(telnetObj.irs);
telnetObj.cmdOutput = telnetObj.stringData.split(telnetObj.irs)
for (var i = 0; i < telnetObj.cmdOutput.length; i++) {
if (telnetObj.cmdOutput[i].search(regexEscape(telnetObj.pageSeparator)) !== -1) {
telnetObj.cmdOutput[i] = telnetObj.cmdOutput[i].replace(telnetObj.pageSeparator, '');
if (telnetObj.cmdOutput[i].length === 0) telnetObj.cmdOutput.splice(i, 1);
telnetObj.cmdOutput[i] = telnetObj.cmdOutput[i].replace(telnetObj.pageSeparator, '')
if (telnetObj.cmdOutput[i].length === 0) telnetObj.cmdOutput.splice(i, 1)
}
}
if (telnetObj.echoLines === 1) telnetObj.cmdOutput.shift();
else if (telnetObj.echoLines > 1) telnetObj.cmdOutput.splice(0, telnetObj.echoLines);
if (telnetObj.echoLines === 1) telnetObj.cmdOutput.shift()
else if (telnetObj.echoLines > 1) telnetObj.cmdOutput.splice(0, telnetObj.echoLines)
// remove prompt
telnetObj.cmdOutput.pop();
telnetObj.cmdOutput.pop()
telnetObj.emit('responseready');
telnetObj.emit('responseready')
}

@@ -195,34 +216,33 @@ }

telnetObj.telnetSocket.write(telnetObj[handle] + telnetObj.ors, function() {
telnetObj.telnetState = 'getprompt';
});
telnetObj.telnetState = 'getprompt'
})
}
}
function negotiate(telnetObj, chunk) {
function negotiate(socket, chunk) {
// info: http://tools.ietf.org/html/rfc1143#section-7
// refuse to start performing and ack the start of performance
// DO -> WONT; WILL -> DO
var packetLength = chunk.length, negData = chunk, cmdData, negResp;
// DO -> WONT WILL -> DO
var packetLength = chunk.length, negData = chunk, cmdData, negResp
for (var i = 0; i < packetLength; i+=3) {
if (chunk[i] != 255) {
negData = chunk.slice(0, i);
cmdData = chunk.slice(i);
break;
negData = chunk.slice(0, i)
cmdData = chunk.slice(i)
break
}
}
negResp = negData.toString('hex').replace(/fd/g, 'fc').replace(/fb/g, 'fd');
negResp = negData.toString('hex').replace(/fd/g, 'fc').replace(/fb/g, 'fd')
if (telnetObj.telnetSocket.writable)
telnetObj.telnetSocket.write(Buffer(negResp, 'hex'));
if (socket.writable) socket.write(Buffer(negResp, 'hex'))
if (cmdData != undefined) return cmdData;
else return;
if (cmdData != undefined) return cmdData
else return
}
function regexEscape(string) {
return string.toString().replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
return string.toString().replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
}
module.exports = Telnet;
module.exports = Telnet

@@ -8,6 +8,9 @@ {

},
"version": "0.2.2",
"version": "0.3.0",
"main": "./lib/telnet-client.js",
"engine": "node >= 0.10.23",
"engine": "node >= 0.10.29",
"license": "MIT",
"dependencies": {
"bluebird": "3.0.5"
},
"devDependencies": {

@@ -29,5 +32,5 @@ "coveralls": "^2.11.x",

"name": "Petar Koretic",
"email": "petar.koretic@sartura.hr"
"email": "petar.koretic@gmail.com"
}
]
}

@@ -20,2 +20,3 @@ [![GitHub license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/mkozjak/node-telnet-client/blob/master/LICENSE)

## Example usage
### Callback-style

@@ -52,2 +53,60 @@ ```js

### Promises
```js
var telnet = require('telnet-client');
var connection = new telnet();
var params = {
host: '127.0.0.1',
port: 23,
shellPrompt: '/ # ',
timeout: 1500,
// removeEcho: 4
};
connection.connect(params)
.then(function(prompt) {
connection.exec(cmd)
.then(function(res) {
console.log('promises result:', res)
})
}, function(error) {
console.log('promises reject:', error)
});
```
### Generators
```js
var co = require('co')
var bluebird = require('bluebird')
var telnet = require('telnet-client');
var connection = new telnet();
var params = {
host: '127.0.0.1',
port: 23,
shellPrompt: '/ # ',
timeout: 1500,
// removeEcho: 4
};
// using 'co'
co(function*() {
yield connection.connect(params)
let res = yield connection.exec(cmd)
console.log('coroutine result:', res)
})
// using 'bluebird'
Promise.coroutine(function*() {
yield connection.connect(params)
let res = yield connection.exec(cmd)
console.log('coroutine result:', res)
})()
```
## API

@@ -60,3 +119,3 @@

### connection.connect(options)
### connection.connect(options) -> Promise

@@ -81,7 +140,9 @@ Creates a new TCP connection to the specified host, where 'options' is an object

### connection.exec(data, [options], [callback])
### connection.exec(data, [options], [callback]) -> Promise
Sends data on the socket (should be a compatible remote host's command if sane information is wanted).
The optional callback parameter will be executed when the data is finally written out - this may not be immediately.
Command result will be passed as the first argument to the callback.
The optional callback parameter will be executed with an error and response when the command is finally written out and the response data has been received.
_*** important notice/API change from 0.3.0 ***_
If there was no error when executing the command, 'error' as the first argument will be undefined.
Command result will be passed as the second argument to the callback.

@@ -99,7 +160,7 @@ Options:

### connection.end()
### connection.end() -> Promise
Half-closes the socket. i.e., it sends a FIN packet. It is possible the server will still send some data.
### connection.destroy()
### connection.destroy() -> Promise

@@ -106,0 +167,0 @@ Ensures that no more I/O activity happens on this socket. Only necessary in case of errors (parse error or so).

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc