UNPKG

domotz-remote-pawn

Version:

Domotz Agent

187 lines (174 loc) 7.28 kB
/** * This file is part of Domotz Agent. * * @license * Domotz Agent is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Domotz Agent is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>. * * @requires module:async * @requires module:events * @requires module:ssh2 * @requires module:q * @requires module:lodash * @requires module:network_tools/sshNode * @copyright Copyright (C) Domotz Inc */ /** * The SSH authentication algorithm parameters * @typedef {Object} SshAlgorithms * @example { cipher: [ 'aes128-gcm', 'aes128-gcm@openssh.com', 'aes256-gcm', 'aes256-gcm@openssh.com' ], kex: [ 'diffie-hellman-group-exchange-sha1', 'diffie-hellman-group-exchange-sha256', 'ecdh-sha2-nistp256', 'ecdh-sha2-nistp384', 'ecdh-sha2-nistp521' ] } * @property {Array.<string>} kex - A List of SSH key exchange methods to use * @property {Array.<string>} cipher - A List of SSH ciphers to use */ /** * The SSH Library Options * @typedef {Object} SshOptions * @property {string} command - The ssh command to execute against the device * @property {int} [timeout] - The time to wait for the command execution * @property {string} [username] - The device username. If not set the custom driver management purpose one is used * @property {string} [password] - The device password. If not set the custom driver management purpose one is used * @property {boolean} [keyboard_interactive=false] - Try keyboard-interactive user authentication if primary user authentication method fails * @property {string} [port=22] - The SSH port * @property {SshAlgorithms} [algorithms] - The SSH Kex and Ciphers to use */ /** * The SSH Command Execution Result * @typedef {callback} SshCallback * @property {string} output - The stdout from the SSH Command execution * @property {ErrorResult} [error] - Will be present if the execution resulted in an error */ /** * The SSH Shell Sequence Options * @typedef {Object} SshShellSequenceOptions * @private * @property {Array.<string>} commands - The ssh commands to execute against the device * @property {string} [username] - The device username. If not set the custom driver management purpose one is used * @property {string} [password] - The device password. If not set the custom driver management purpose one is used * @property {boolean} [keyboard_interactive=false] - Try keyboard-interactive user authentication if primary user authentication method fails* * @property {string} [prompt=#] - The device ssh prompt expected. If not set correctly it may result in a timeout * @property {string} [prompt_regex] - The device ssh prompt regular expression expected. Used if a device prompt changes during ssh sequence execution * @property {string} [error_prompt] - The device error prompt expected. Used when there is an expected error prompt string to halt the execution * @property {int} [inter_command_timeout_ms=1000] - Timeout to wait between ssh sequence commands executions * @property {int} [global_timeout_ms=30000] - The global ssh shell sequence execution timeout. When expired results in TIMEOUT_ERROR * @property {string} [port=22] - The SSH port * @property {SshAlgorithms} [algorithms] - The SSH Kex and Ciphers to use */ /** * The SSH Shell Sequence callback * @typedef {callback} SshShellSequenceCallback * @private * @property {Array.<string>} outputs - The output list of the SSH Commands executions * @property {ErrorResult} [error] - Will be present if the execution resulted in an error */ var async = require('async'); var events = require('events'); var ssh2 = require('ssh2'); var q = require('q'); var lodash = require('lodash'); var sandboxConsole; /** * SSH Library Resource Locator object * @private * @readonly */ function createResourceLocator() { var sandboxResourceLocator = { log: { decorateLogs: function () { return sandboxConsole; }, }, ssh2: ssh2, q: q, async: async, lodash: lodash, events: events, utils: { proc: {}, platform: domotzPlatform, }, networkTools: {}, }; sandboxResourceLocator.networkTools.systemSSH = require('../../network_tools/sshSystemShellSequence').factory(sandboxResourceLocator); return sandboxResourceLocator; } var fs = require('fs'); var domotzPlatform = require('../../../src/utils/platform').factory(fs); /** * Sends a sequence of SSH commands * @function * @private * @readonly * @param {Object} myConsole - The Domotz Sandbox console * @param {SshShellSequenceOptions} options - The SSH Commands execution options */ function sendSSHShellSequence(myConsole, options, callback) { sandboxConsole = myConsole; var sandboxResourceLocator = createResourceLocator(); function outputTransformer(result) { var error = result.error; var outputs = []; if (result.output) { result.output.forEach(function (item) { outputs.push(Buffer(item, 'base64').toString()); }); } callback(outputs, error); } var sshNode = require('../../network_tools/sshNode').factory(sandboxResourceLocator); return sshNode.sshShellSequence(options, outputTransformer); } /** * Sends an SSH command * @function * @private * @readonly * @param {Object} myConsole - The Domotz Sandbox console * @param {SshOptions} options - The SSH Command execution options */ function sendSSHCommand(myConsole, options, callback) { sandboxConsole = myConsole; var sandboxResourceLocator = createResourceLocator(); var command = options.command; if (options.command) { delete options.command; } else { throw Error("D.sendSSHCommand requires a 'command' in its options parameter"); } var sshNode = require('../../network_tools/sshNode').factory(sandboxResourceLocator); var promise = sshNode.exec(command, options, ''); return promise .then(function (stdout) { callback(stdout, null); }) .catch(function (stderr) { sandboxConsole.error('SSH Command execution Error: ' + JSON.stringify(stderr)); callback(null, stderr); }); } module.exports.sendSSHCommand = sendSSHCommand; module.exports.sendSSHShellSequence = sendSSHShellSequence;