first commit

This commit is contained in:
s.golasch
2023-08-01 13:49:46 +02:00
commit 1fc239fd54
20238 changed files with 3112246 additions and 0 deletions

243
build/node_modules/ssh2/examples/server-chat.js generated vendored Normal file
View 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();
}

View 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);
});