2015-02-10 19:41:24 +00:00
|
|
|
/**
|
|
|
|
* @copyright Copyright(c) 2011 Ajax.org B.V. <info AT ajax.org>
|
|
|
|
* @author Fabian Jakobs <fabian AT ajax DOT org>
|
|
|
|
* @author Mike de Boer <mike AT ajax DOT org>
|
|
|
|
* @license http://github.com/ajaxorg/node-sftp/blob/master/LICENSE MIT License
|
|
|
|
*/
|
|
|
|
|
2015-03-25 12:25:28 +00:00
|
|
|
"use strict";
|
|
|
|
|
2015-02-10 19:41:24 +00:00
|
|
|
var child_process = require("child_process");
|
|
|
|
var fs = require("fs");
|
2015-03-25 12:25:28 +00:00
|
|
|
var tmp = require("tmp");
|
|
|
|
var debug = require("debug")("ssh");
|
2015-02-10 19:41:24 +00:00
|
|
|
|
|
|
|
exports.buildArgs = function(prvkeyFile, host) {
|
|
|
|
var args = [
|
|
|
|
"-o", "PasswordAuthentication=no",
|
|
|
|
"-o", "IdentityFile=" + prvkeyFile,
|
|
|
|
"-o", "UserKnownHostsFile=/dev/null",
|
|
|
|
"-o", "StrictHostKeyChecking=no",
|
2015-08-19 12:02:36 +00:00
|
|
|
"-o", "IdentitiesOnly=yes",
|
2015-02-10 19:41:24 +00:00
|
|
|
"-F", "/dev/null", // use empty config file to not depend on local settings
|
|
|
|
// force pseudo terminal to make sure that the remote process is killed
|
|
|
|
// when the local ssh process is killed
|
|
|
|
"-t", "-t",
|
|
|
|
"-o", "BatchMode=yes",
|
|
|
|
"-o", "ConnectTimeout=10" // default timeout is 2 minutes, which is quite long
|
|
|
|
];
|
|
|
|
|
|
|
|
if (host) {
|
|
|
|
host = host.split(":");
|
|
|
|
args.push("-p", host[1] || 22);
|
|
|
|
args.push(host[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return args;
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.spawnWithKeyFile = function(prvkeyFile, host, command, args) {
|
|
|
|
var sshArgs = exports.buildArgs(prvkeyFile, host);
|
|
|
|
|
2015-03-25 12:25:28 +00:00
|
|
|
args = sshArgs.concat(command ? [command] : []).concat(args || []);
|
|
|
|
debug("executing: ssh " + args.join(" "));
|
2015-02-10 19:41:24 +00:00
|
|
|
|
|
|
|
return child_process.spawn("ssh", args);
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.writeKeyFile = function(prvkey, callback) {
|
2015-03-25 12:25:28 +00:00
|
|
|
tmp.tmpName(function(err, filename) {
|
|
|
|
if (err) return callback(err);
|
|
|
|
|
|
|
|
fs.writeFile(filename, prvkey, function(err) {
|
|
|
|
if (err) return callback(err);
|
|
|
|
|
|
|
|
fs.chmod(filename, "0600", function(err) {
|
|
|
|
callback(err, filename);
|
|
|
|
});
|
2015-02-10 19:41:24 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.writeKeyFiles = function(prvkey, pubkey, callback) {
|
2015-03-25 12:25:28 +00:00
|
|
|
tmp.tmpName(function(err, filename) {
|
|
|
|
if (err) return callback(err);
|
|
|
|
|
|
|
|
fs.writeFile(filename, prvkey, function(err) {
|
|
|
|
if (err) return callback(err);
|
|
|
|
|
|
|
|
fs.chmod(filename, "0600", function(err) {
|
|
|
|
if (err) return callback(err);
|
|
|
|
|
|
|
|
fs.writeFile(filename + ".pub", pubkey, function(err) {
|
|
|
|
if (err) return callback(err);
|
|
|
|
|
|
|
|
fs.chmod(filename + ".pub", "0600", function(err) {
|
|
|
|
callback(err, filename);
|
|
|
|
});
|
2015-02-10 19:41:24 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.spawn = function(prvkey, host, command, args, callback) {
|
|
|
|
exports.writeKeyFile(prvkey, function(err, filename) {
|
2015-03-25 12:25:28 +00:00
|
|
|
if (err) return callback(err);
|
|
|
|
|
2015-02-10 19:41:24 +00:00
|
|
|
var child = exports.spawnWithKeyFile(filename, host, command, args);
|
|
|
|
|
|
|
|
child.on("exit", function(code) {
|
|
|
|
fs.unlink(filename, function() {});
|
|
|
|
});
|
|
|
|
|
|
|
|
callback(null, child);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.exec = function(prvkey, host, command, args, callback) {
|
|
|
|
exports.spawn(prvkey, host, command, args, function(err, child) {
|
|
|
|
if (err)
|
|
|
|
return callback(err);
|
|
|
|
|
|
|
|
var out = err = "";
|
|
|
|
|
|
|
|
child.stdout.on("data", function (data) {
|
|
|
|
out += data;
|
|
|
|
});
|
|
|
|
|
|
|
|
child.stderr.on("data", function (data) {
|
|
|
|
err += data;
|
|
|
|
});
|
|
|
|
|
|
|
|
child.on("exit", function(code) {
|
|
|
|
callback(code, out, err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.generateKeyPair = function(email, callback) {
|
2015-03-25 12:25:28 +00:00
|
|
|
tmp.tmpName(function(err, filename) {
|
|
|
|
if (err) return callback(err);
|
|
|
|
|
|
|
|
var phrase = "";
|
|
|
|
|
|
|
|
var command = "ssh-keygen -t rsa " +
|
2016-04-06 16:34:34 +00:00
|
|
|
"-b 4096 " +
|
2015-03-25 12:25:28 +00:00
|
|
|
"-f \"" + filename + "\" " +
|
|
|
|
"-P \"" + phrase + "\" " +
|
|
|
|
"-C \"" + email + "\" ";
|
|
|
|
|
|
|
|
child_process.exec(command, function (err, stdout, stderr) {
|
|
|
|
if (err) return callback(err);
|
|
|
|
|
|
|
|
fs.readFile(filename + ".pub", function (err, pubkey) {
|
|
|
|
if (err) return callback(err);
|
|
|
|
|
|
|
|
fs.readFile(filename, function (err, prvkey) {
|
|
|
|
if (err) return callback(err);
|
|
|
|
|
|
|
|
fs.unlink(filename + ".pub", function() {
|
|
|
|
fs.unlink(filename, function() {
|
|
|
|
callback(null, pubkey.toString(), prvkey.toString());
|
|
|
|
});
|
2015-02-10 19:41:24 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.validateSSHKey = function(prvkey, host, callback) {
|
|
|
|
exports.exec(prvkey, host, "", [], function(err, stdout, stderr) {
|
2015-08-19 12:02:36 +00:00
|
|
|
debug("out >> " + stdout);
|
|
|
|
debug("err >> " + stderr);
|
|
|
|
debug(err);
|
2015-02-10 19:41:24 +00:00
|
|
|
callback(null, !stderr.match(/Permission denied \(.*publickey/));
|
|
|
|
});
|
|
|
|
};
|