cleanup
This commit is contained in:
parent
ae452367c0
commit
a5c448902e
107
bin/telebitd.js
107
bin/telebitd.js
|
@ -31,6 +31,8 @@ var connectTimes = [];
|
||||||
var isConnected = false;
|
var isConnected = false;
|
||||||
var eggspress = require('../lib/eggspress.js');
|
var eggspress = require('../lib/eggspress.js');
|
||||||
var keypairs = require('keypairs');
|
var keypairs = require('keypairs');
|
||||||
|
var KEYEXT = '.key.jwk.json';
|
||||||
|
var PUBEXT = '.pub.jwk.json';
|
||||||
|
|
||||||
var TelebitRemote = require('../lib/daemon/index.js').TelebitRemote;
|
var TelebitRemote = require('../lib/daemon/index.js').TelebitRemote;
|
||||||
|
|
||||||
|
@ -140,8 +142,7 @@ controllers.http = function (req, res) {
|
||||||
|
|
||||||
if (!req.body) {
|
if (!req.body) {
|
||||||
res.statusCode = 422;
|
res.statusCode = 422;
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({"error":{"message":"module \'http\' needs some arguments"}});
|
||||||
res.end(JSON.stringify({"error":{"message":"module \'http\' needs some arguments"}}));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,8 +154,7 @@ controllers.http = function (req, res) {
|
||||||
|
|
||||||
if (!portOrPath) {
|
if (!portOrPath) {
|
||||||
res.statusCode = 422;
|
res.statusCode = 422;
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({ error: { message: "module 'http' needs port or path" } });
|
||||||
res.end(JSON.stringify({ error: { message: "module 'http' needs port or path" } }));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,22 +249,20 @@ controllers.http = function (req, res) {
|
||||||
}
|
}
|
||||||
state.config.servernames = state.servernames;
|
state.config.servernames = state.servernames;
|
||||||
saveConfig(function (err) {
|
saveConfig(function (err) {
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({
|
||||||
res.end(JSON.stringify({
|
|
||||||
success: true
|
success: true
|
||||||
, active: active
|
, active: active
|
||||||
, remote: remoteHost
|
, remote: remoteHost
|
||||||
, local: portOrPath
|
, local: portOrPath
|
||||||
, saved: !err
|
, saved: !err
|
||||||
, module: 'http'
|
, module: 'http'
|
||||||
}));
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
controllers.tcp = function (req, res) {
|
controllers.tcp = function (req, res) {
|
||||||
if (!req.body) {
|
if (!req.body) {
|
||||||
res.statusCode = 422;
|
res.statusCode = 422;
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({ error: { message: "module 'tcp' needs more arguments" } });
|
||||||
res.end(JSON.stringify({ error: { message: "module 'tcp' needs more arguments" } }));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,22 +296,20 @@ controllers.tcp = function (req, res) {
|
||||||
}
|
}
|
||||||
state.config.ports = state.ports;
|
state.config.ports = state.ports;
|
||||||
saveConfig(function (err) {
|
saveConfig(function (err) {
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({
|
||||||
res.end(JSON.stringify({
|
|
||||||
success: true
|
success: true
|
||||||
, active: active
|
, active: active
|
||||||
, remote: remotePort
|
, remote: remotePort
|
||||||
, local: portOrPath
|
, local: portOrPath
|
||||||
, saved: !err
|
, saved: !err
|
||||||
, module: 'tcp'
|
, module: 'tcp'
|
||||||
}));
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
controllers.ssh = function (req, res) {
|
controllers.ssh = function (req, res) {
|
||||||
if (!req.body) {
|
if (!req.body) {
|
||||||
res.statusCode = 422;
|
res.statusCode = 422;
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({"error":{"message":"module 'ssh' needs more arguments"}});
|
||||||
res.end(JSON.stringify({"error":{"message":"module 'ssh' needs more arguments"}}));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,15 +320,14 @@ controllers.ssh = function (req, res) {
|
||||||
if (false !== local && !local) {
|
if (false !== local && !local) {
|
||||||
local = 22;
|
local = 22;
|
||||||
}
|
}
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({
|
||||||
res.end(JSON.stringify({
|
|
||||||
success: true
|
success: true
|
||||||
, active: true
|
, active: true
|
||||||
, remote: Object.keys(state.config.ports)[0]
|
, remote: Object.keys(state.config.ports)[0]
|
||||||
, local: local
|
, local: local
|
||||||
, saved: !err
|
, saved: !err
|
||||||
, module: 'ssh'
|
, module: 'ssh'
|
||||||
}));
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,8 +346,7 @@ controllers.ssh = function (req, res) {
|
||||||
sshAuto = parseInt(sshAuto, 10);
|
sshAuto = parseInt(sshAuto, 10);
|
||||||
if (!sshAuto || sshAuto <= 0 || sshAuto > 65535) {
|
if (!sshAuto || sshAuto <= 0 || sshAuto > 65535) {
|
||||||
res.statusCode = 400;
|
res.statusCode = 400;
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({ error: { message: "bad ssh_auto option '" + rawSshAuto + "'" } });
|
||||||
res.end(JSON.stringify({ error: { message: "bad ssh_auto option '" + rawSshAuto + "'" } }));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.config.sshAuto = sshAuto;
|
state.config.sshAuto = sshAuto;
|
||||||
|
@ -361,15 +355,13 @@ controllers.ssh = function (req, res) {
|
||||||
controllers.relay = function (req, res) {
|
controllers.relay = function (req, res) {
|
||||||
if (!req.body) {
|
if (!req.body) {
|
||||||
res.statusCode = 422;
|
res.statusCode = 422;
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({"error":{"message":"module \'relay\' needs more arguments"}});
|
||||||
res.end(JSON.stringify({"error":{"message":"module \'relay\' needs more arguments"}}));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return urequestAsync(req.body).then(function (resp) {
|
return urequestAsync(req.body).then(function (resp) {
|
||||||
res.setHeader('Content-Type', 'application/json');
|
|
||||||
resp = resp.toJSON();
|
resp = resp.toJSON();
|
||||||
res.end(JSON.stringify(resp));
|
res.send(resp);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
controllers._nonces = {};
|
controllers._nonces = {};
|
||||||
|
@ -378,7 +370,7 @@ controllers._requireNonce = function (req, res, next) {
|
||||||
var active = (Date.now() - controllers._nonces[nonce]) < (4 * 60 * 60 * 1000);
|
var active = (Date.now() - controllers._nonces[nonce]) < (4 * 60 * 60 * 1000);
|
||||||
if (!active) {
|
if (!active) {
|
||||||
// TODO proper headers and error message
|
// TODO proper headers and error message
|
||||||
res.end({ "error": "invalid or expired nonce", "error_code": "ENONCE" });
|
res.send({ "error": "invalid or expired nonce", "error_code": "ENONCE" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
delete controllers._nonces[nonce];
|
delete controllers._nonces[nonce];
|
||||||
|
@ -451,7 +443,7 @@ function jsonEggspress(req, res, next) {
|
||||||
req.body = JSON.parse(body);
|
req.body = JSON.parse(body);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
res.statusCode = 400;
|
res.statusCode = 400;
|
||||||
res.end('{"error":{"message":"POST body is not valid json"}}');
|
res.send({"error":{"message":"POST body is not valid json"}});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
|
@ -508,12 +500,12 @@ function jwsEggspress(req, res, next) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var vjwk;
|
var vjwk;
|
||||||
jwks.some(function (jwk) {
|
DB.pubs.some(function (jwk) {
|
||||||
if (jwk.kid === req.jws.header.kid) {
|
if (jwk.kid === req.jws.header.kid) {
|
||||||
vjwk = jwk;
|
vjwk = jwk;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if ((0 === jwks.length && req.jws.header.jwk)) {
|
if ((0 === DB.pubs.length && req.jws.header.jwk)) {
|
||||||
vjwk = req.jws.header.jwk;
|
vjwk = req.jws.header.jwk;
|
||||||
if (!vjwk.kid) { throw Error("Impossible: no key id"); }
|
if (!vjwk.kid) { throw Error("Impossible: no key id"); }
|
||||||
}
|
}
|
||||||
|
@ -524,7 +516,7 @@ function jwsEggspress(req, res, next) {
|
||||||
}
|
}
|
||||||
req.jws.verified = verified;
|
req.jws.verified = verified;
|
||||||
|
|
||||||
if (0 !== jwks.length) {
|
if (0 !== DB.pubs.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return keystore.set(vjwk.kid + '.pub.jwk.json', vjwk);
|
return keystore.set(vjwk.kid + '.pub.jwk.json', vjwk);
|
||||||
|
@ -565,15 +557,14 @@ function handleApi() {
|
||||||
dumpy.message = "Please run 'telebit init' to authenticate.";
|
dumpy.message = "Please run 'telebit init' to authenticate.";
|
||||||
}
|
}
|
||||||
|
|
||||||
res.end(JSON.stringify(dumpy));
|
res.send(dumpy);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConfigOnly(req, res) {
|
function getConfigOnly(req, res) {
|
||||||
var resp = JSON.parse(JSON.stringify(state.config));
|
var resp = JSON.parse(JSON.stringify(state.config));
|
||||||
resp.version = pkg.version;
|
resp.version = pkg.version;
|
||||||
resp._otp = state.otp;
|
resp._otp = state.otp;
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send(resp);
|
||||||
res.end(JSON.stringify(resp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -585,9 +576,8 @@ function handleApi() {
|
||||||
fs.writeFile(confpath, YAML.safeDump(snakeCopy(state.config)), function (err) {
|
fs.writeFile(confpath, YAML.safeDump(snakeCopy(state.config)), function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
res.statusCode = 500;
|
res.statusCode = 500;
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({"error":{"message":"Could not save config file after init: " + err.message.replace(/"/g, "'")
|
||||||
res.end('{"error":{"message":"Could not save config file after init: ' + err.message.replace(/"/g, "'")
|
+ ".\nPerhaps check that the file exists and your user has permissions to write it?"}});
|
||||||
+ '.\nPerhaps check that the file exists and your user has permissions to write it?"}}');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,7 +589,7 @@ function handleApi() {
|
||||||
var conf = {};
|
var conf = {};
|
||||||
if (!req.body) {
|
if (!req.body) {
|
||||||
res.statusCode = 422;
|
res.statusCode = 422;
|
||||||
res.end('{"error":{"message":"module \'init\' needs more arguments"}}');
|
res.send({"error":{"message":"module 'init' needs more arguments"}});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,8 +685,7 @@ function handleApi() {
|
||||||
console.warn('missing config');
|
console.warn('missing config');
|
||||||
res.statusCode = 400;
|
res.statusCode = 400;
|
||||||
|
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({
|
||||||
res.end(JSON.stringify({
|
|
||||||
error: {
|
error: {
|
||||||
code: "E_INIT"
|
code: "E_INIT"
|
||||||
, message: "Missing important config file params"
|
, message: "Missing important config file params"
|
||||||
|
@ -704,7 +693,7 @@ function handleApi() {
|
||||||
, _config: JSON.stringify(state.config)
|
, _config: JSON.stringify(state.config)
|
||||||
, _body: JSON.stringify(req.body)
|
, _body: JSON.stringify(req.body)
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -729,8 +718,7 @@ function handleApi() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function respondAndClose() {
|
function respondAndClose() {
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({ success: true });
|
||||||
res.end(JSON.stringify({ success: true }));
|
|
||||||
controlServer.close(function () {
|
controlServer.close(function () {
|
||||||
console.info("[telebitd.js] server closed");
|
console.info("[telebitd.js] server closed");
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
|
@ -751,10 +739,9 @@ function handleApi() {
|
||||||
}
|
}
|
||||||
|
|
||||||
res.statusCode = 400;
|
res.statusCode = 400;
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({
|
||||||
res.end(JSON.stringify({
|
|
||||||
error: { code: "E_CONFIG", message: "Invalid config file. Please run 'telebit init'" }
|
error: { code: "E_CONFIG", message: "Invalid config file. Please run 'telebit init'" }
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveAndCommit(req, res) {
|
function saveAndCommit(req, res) {
|
||||||
|
@ -763,10 +750,9 @@ function handleApi() {
|
||||||
fs.writeFile(confpath, YAML.safeDump(snakeCopy(state.config)), function (err) {
|
fs.writeFile(confpath, YAML.safeDump(snakeCopy(state.config)), function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
res.statusCode = 500;
|
res.statusCode = 500;
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({
|
||||||
res.end(JSON.stringify({
|
|
||||||
"error":{"message":"Could not save config file. Perhaps you're not running as root?"}
|
"error":{"message":"Could not save config file. Perhaps you're not running as root?"}
|
||||||
}));
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
listSuccess();
|
listSuccess();
|
||||||
|
@ -775,10 +761,9 @@ function handleApi() {
|
||||||
|
|
||||||
function handleError(err, req, res) {
|
function handleError(err, req, res) {
|
||||||
res.statusCode = 500;
|
res.statusCode = 500;
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({
|
||||||
res.end(JSON.stringify({
|
|
||||||
error: { message: err.message, code: err.code }
|
error: { message: err.message, code: err.code }
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function enable(req, res) {
|
function enable(req, res) {
|
||||||
|
@ -808,21 +793,19 @@ function handleApi() {
|
||||||
|
|
||||||
if (myRemote) { myRemote.end(); myRemote = null; }
|
if (myRemote) { myRemote.end(); myRemote = null; }
|
||||||
fs.writeFile(confpath, YAML.safeDump(snakeCopy(state.config)), function (err) {
|
fs.writeFile(confpath, YAML.safeDump(snakeCopy(state.config)), function (err) {
|
||||||
res.setHeader('Content-Type', 'application/json');
|
|
||||||
if (err) {
|
if (err) {
|
||||||
err.message = "Could not save config file. Perhaps you're user doesn't have permission?";
|
err.message = "Could not save config file. Perhaps you're user doesn't have permission?";
|
||||||
handleError(err);
|
handleError(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
res.end('{"success":true}');
|
res.send({"success":true});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatus(req, res) {
|
function getStatus(req, res) {
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
res.setHeader('Content-Type', 'application/json');
|
|
||||||
require('../lib/ssh.js').checkSecurity().then(function (ssh) {
|
require('../lib/ssh.js').checkSecurity().then(function (ssh) {
|
||||||
res.end(JSON.stringify(
|
res.send(
|
||||||
{ module: 'status'
|
{ module: 'status'
|
||||||
, version: pkg.version
|
, version: pkg.version
|
||||||
, port: (state.config.ipc && state.config.ipc.port || state._ipc.port || undefined)
|
, port: (state.config.ipc && state.config.ipc.port || state._ipc.port || undefined)
|
||||||
|
@ -840,7 +823,7 @@ function handleApi() {
|
||||||
, ssh_password_authentication: ssh.password_authentication
|
, ssh_password_authentication: ssh.password_authentication
|
||||||
, ssh_requests_password: ssh.requests_password
|
, ssh_requests_password: ssh.requests_password
|
||||||
}
|
}
|
||||||
));
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,8 +859,7 @@ function handleApi() {
|
||||||
app.use(/\b(status)\b/, getStatus);
|
app.use(/\b(status)\b/, getStatus);
|
||||||
app.use(/\b(list)\b/, listSuccess);
|
app.use(/\b(list)\b/, listSuccess);
|
||||||
app.use('/', function (req, res) {
|
app.use('/', function (req, res) {
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.send({"error":{"message":"unrecognized rpc"}});
|
||||||
res.end(JSON.stringify({"error":{"message":"unrecognized rpc"}}));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
|
@ -1430,7 +1412,8 @@ state.net = state.net || {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var jwks = [];
|
var DB = {};
|
||||||
|
DB.pubs = [];
|
||||||
var token;
|
var token;
|
||||||
var tokenname = "access_token.jwt";
|
var tokenname = "access_token.jwt";
|
||||||
try {
|
try {
|
||||||
|
@ -1444,12 +1427,10 @@ try {
|
||||||
} catch(e) { onKeystore(); }
|
} catch(e) { onKeystore(); }
|
||||||
function onKeystore() {
|
function onKeystore() {
|
||||||
return keystore.all().then(function (list) {
|
return keystore.all().then(function (list) {
|
||||||
var keyext = '.key.jwk.json';
|
|
||||||
var pubext = '.pub.jwk.json';
|
|
||||||
var key;
|
var key;
|
||||||
list.forEach(function (el) {
|
list.forEach(function (el) {
|
||||||
// find key
|
// find key
|
||||||
if (keyext === el.account.slice(-keyext.length)
|
if (KEYEXT === el.account.slice(-KEYEXT.length)
|
||||||
&& el.password.kty && el.password.kid) {
|
&& el.password.kty && el.password.kid) {
|
||||||
key = el.password;
|
key = el.password;
|
||||||
return;
|
return;
|
||||||
|
@ -1465,9 +1446,9 @@ function onKeystore() {
|
||||||
// (if we sign these we could probably just store them to the fs,
|
// (if we sign these we could probably just store them to the fs,
|
||||||
// but we do want some way to know that they weren't just willy-nilly
|
// but we do want some way to know that they weren't just willy-nilly
|
||||||
// added to the fs my any old program)
|
// added to the fs my any old program)
|
||||||
if (pubext === el.account.slice(-pubext.length)) {
|
if (PUBEXT === el.account.slice(-PUBEXT.length)) {
|
||||||
// pre-parsed
|
// pre-parsed
|
||||||
jwks.push(el.password);
|
DB.pubs.push(el.password);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1485,7 +1466,7 @@ function onKeystore() {
|
||||||
var jwk = pair.private;
|
var jwk = pair.private;
|
||||||
return keypairs.thumbprint({ jwk: jwk }).then(function (kid) {
|
return keypairs.thumbprint({ jwk: jwk }).then(function (kid) {
|
||||||
jwk.kid = kid;
|
jwk.kid = kid;
|
||||||
return keystore.set(kid + keyext, jwk).then(function () {
|
return keystore.set(kid + KEYEXT, jwk).then(function () {
|
||||||
var size = (jwk.crv || Buffer.from(jwk.n, 'base64').byteLength * 8);
|
var size = (jwk.crv || Buffer.from(jwk.n, 'base64').byteLength * 8);
|
||||||
console.info("Generated new %s %s private key with thumbprint %s", jwk.kty, size, kid);
|
console.info("Generated new %s %s private key with thumbprint %s", jwk.kty, size, kid);
|
||||||
state.key = jwk;
|
state.key = jwk;
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
function eggSend(obj) {
|
||||||
|
/*jslint validthis: true*/
|
||||||
|
var me = this;
|
||||||
|
if (!me.getHeader('content-type')) {
|
||||||
|
me.setHeader('Content-Type', 'application/json');
|
||||||
|
}
|
||||||
|
me.end(JSON.stringify(obj));
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = function eggspress() {
|
module.exports = function eggspress() {
|
||||||
//var patternsMap = {};
|
//var patternsMap = {};
|
||||||
var allPatterns = [];
|
var allPatterns = [];
|
||||||
|
@ -52,6 +61,9 @@ module.exports = function eggspress() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res.send = eggSend;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ module.exports.create = function (state) {
|
||||||
}
|
}
|
||||||
, payload: JSON.stringify(opts.data)
|
, payload: JSON.stringify(opts.data)
|
||||||
}).then(function (jws) {
|
}).then(function (jws) {
|
||||||
req.setHeader("content-type", 'application/json');
|
req.setHeader("Content-Type", 'application/jose+json');
|
||||||
req.write(JSON.stringify(jws));
|
req.write(JSON.stringify(jws));
|
||||||
req.end();
|
req.end();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue