mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-02-12 11:01:52 +00:00
Added support for MeshCmd routing.
This commit is contained in:
parent
951e6236f9
commit
e75adafb05
21 changed files with 343 additions and 70 deletions
BIN
agents/MeshConsole.exe
Normal file
BIN
agents/MeshConsole.exe
Normal file
Binary file not shown.
BIN
agents/MeshConsole64.exe
Normal file
BIN
agents/MeshConsole64.exe
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
170
agents/meshcmd.js
Normal file
170
agents/meshcmd.js
Normal file
|
@ -0,0 +1,170 @@
|
|||
var fs = require('fs');
|
||||
var os = require('os');
|
||||
var net = require('net');
|
||||
var http = require('http');
|
||||
var dgram = require('dgram');
|
||||
var httpHeaders = require('http-headers');
|
||||
var tcpserver = null;
|
||||
var broadcastSockets = {};
|
||||
var multicastSockets = {};
|
||||
var discoveryInterval = null;
|
||||
var membershipIPv4 = '239.255.255.235';
|
||||
var membershipIPv6 = 'FF02:0:0:0:0:0:0:FE';
|
||||
|
||||
/*
|
||||
// Route Settings
|
||||
var settings = {
|
||||
action: 'route',
|
||||
localPort: 1234,
|
||||
remoteName: 'AmtMachine7',
|
||||
remoteNodeId: 'node//nmiPnDhT3vHKu$zg296YC5RjK53Trgh3Cimx3K8GVrFh$xch0UAAett2rbJpeddc',
|
||||
remotePort: 3389,
|
||||
username: 'a',
|
||||
password: 'a',
|
||||
serverUrl: 'wss://devbox.mesh.meshcentral.com:443/meshrelay.ashx',
|
||||
serverId: 'D99362D5ED8BAEA8BF9E743B34B242256370C460FD66CB62373C6CFCB204D6D707403E396CF0EF6DC2B3A42F735135FD', // SHA384 of server HTTPS public key
|
||||
serverHttpsHash: 'D9DE9E27A229B5355708A3672FB23237CC994A680B3570D242A91E36B4AE5BC9', // SHA256 of server HTTPS certificate
|
||||
debugLevel: 0
|
||||
}
|
||||
*/
|
||||
|
||||
// Check the server certificate fingerprint
|
||||
function onVerifyServer(clientName, certs) {
|
||||
try { for (var i in certs) { if (certs[i].fingerprint.replace(/:/g, '') == settings.serverHttpsHash) { return; } } } catch (e) { }
|
||||
if (serverhash != null) { console.log('Error: Failed to verify server certificate.'); return false; }
|
||||
}
|
||||
|
||||
// Print a debug message
|
||||
function debug(level, message) { if ((settings.debugLevel != null) && (settings.debugLevel >= level)) { console.log(message); } }
|
||||
|
||||
// Start the router, start by listening to the local port
|
||||
function run(argv) {
|
||||
console.log('MeshCentral Command v1.0');
|
||||
var actionpath = 'meshaction.txt';
|
||||
if (argv.length >= 2) { actionpath = argv[1]; }
|
||||
|
||||
// Load the action file
|
||||
var actionfile = null;
|
||||
try { actionfile = fs.readFileSync(actionpath); } catch (e) { }
|
||||
if (actionfile == null) { console.log('Unable to load \"' + actionpath + '\". Create this file or specify the location as the first argument.'); process.exit(1); }
|
||||
try { settings = JSON.parse(actionfile); } catch (e) { console.log(actionpath, e); process.exit(1); }
|
||||
|
||||
// Validate meshaction.txt
|
||||
if (settings.action == null) { console.log('No \"action\" specified.'); process.exit(1); }
|
||||
settings.action = settings.action.toLowerCase();
|
||||
if (settings.action == 'route') {
|
||||
if ((settings.localPort == null) || (typeof settings.localPort != 'number') || (settings.localPort < 0) || (settings.localPort > 65535)) { console.log('No or invalid \"localPort\" specified.'); process.exit(1); }
|
||||
if ((settings.remoteNodeId == null) || (typeof settings.remoteNodeId != 'string')) { console.log('No or invalid \"remoteNodeId\" specified.'); process.exit(1); }
|
||||
if ((settings.username == null) || (typeof settings.username != 'string')) { console.log('No or invalid \"username\" specified.'); process.exit(1); }
|
||||
if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified.'); process.exit(1); }
|
||||
if ((settings.serverId == null) || (typeof settings.serverId != 'string') || (settings.serverId.length != 96)) { console.log('No or invalid \"serverId\" specified.'); process.exit(1); }
|
||||
if ((settings.serverHttpsHash == null) || (typeof settings.serverHttpsHash != 'string') || (settings.serverHttpsHash.length != 96)) { console.log('No or invalid \"serverHttpsHash\" specified.'); process.exit(1); }
|
||||
if ((settings.remotePort == null) || (typeof settings.remotePort != 'number') || (settings.remotePort < 0) || (settings.remotePort > 65535)) { console.log('No or invalid \"remotePort\" specified.'); process.exit(1); }
|
||||
} else {
|
||||
console.log('Invalid \"action\" specified.'); process.exit(1);
|
||||
}
|
||||
|
||||
debug(1, "Settings: " + JSON.stringify(settings));
|
||||
if (settings.serverUrl != null) { startRouter(); } else { discoverMeshServer(); }
|
||||
}
|
||||
|
||||
// Starts the router
|
||||
function startRouter() {
|
||||
tcpserver = net.createServer(OnTcpClientConnected);
|
||||
tcpserver.on('error', function (err) { console.log(err); process.exit(0); });
|
||||
tcpserver.listen(settings.localPort, function () {
|
||||
// We started listening.
|
||||
if (settings.remoteName == null) {
|
||||
console.log('Redirecting local port ' + settings.localPort + ' to remote port ' + settings.remotePort + '.');
|
||||
} else {
|
||||
console.log('Redirecting local port ' + settings.localPort + ' to ' + settings.remoteName + ':' + settings.remotePort + '.');
|
||||
}
|
||||
console.log('Press ctrl-c to terminal.');
|
||||
|
||||
// If settings has a "cmd", run it now.
|
||||
//process.exec("notepad.exe");
|
||||
});
|
||||
}
|
||||
|
||||
// Called when a TCP connect is received on the local port. Launch a tunnel.
|
||||
function OnTcpClientConnected(c) {
|
||||
try {
|
||||
// 'connection' listener
|
||||
debug(1, 'Client connected');
|
||||
c.on('end', function () { disconnectTunnel(this, this.websocket, 'Client closed'); });
|
||||
c.pause();
|
||||
|
||||
try {
|
||||
options = http.parseUri(settings.serverUrl + '?user=' + settings.username + '&pass=' + settings.password + '&nodeid=' + settings.remoteNodeId + '&tcpport=' + settings.remotePort);
|
||||
} catch (e) { console.log('Unable to parse \"serverUrl\".'); process.exit(1); }
|
||||
options.checkServerIdentity = onVerifyServer;
|
||||
c.websocket = http.request(options);
|
||||
c.websocket.tcp = c;
|
||||
c.websocket.tunneling = false;
|
||||
c.websocket.upgrade = OnWebSocket;
|
||||
c.websocket.on('error', function (msg) { console.log(msg); });
|
||||
c.websocket.end();
|
||||
} catch (e) { debug(2, e); }
|
||||
}
|
||||
|
||||
// Disconnect both TCP & WebSocket connections and display a message.
|
||||
function disconnectTunnel(tcp, ws, msg) {
|
||||
if (ws != null) { try { ws.end(); } catch (e) { debug(2, e); } }
|
||||
if (tcp != null) { try { tcp.end(); } catch (e) { debug(2, e); } }
|
||||
debug(1, 'Tunnel disconnected: ' + msg);
|
||||
}
|
||||
|
||||
// Called when the web socket gets connected
|
||||
function OnWebSocket(msg, s, head) {
|
||||
debug(1, 'Websocket connected');
|
||||
s.on('data', function (msg) {
|
||||
if (this.parent.tunneling == false) {
|
||||
msg = msg.toString();
|
||||
if (msg == 'c') {
|
||||
this.parent.tunneling = true; this.pipe(this.parent.tcp); this.parent.tcp.pipe(this); debug(1, 'Tunnel active');
|
||||
} else if ((msg.length > 6) && (msg.substring(0, 6) == 'error:')) {
|
||||
console.log(msg.substring(6));
|
||||
disconnectTunnel(this.tcp, this, msg.substring(6));
|
||||
}
|
||||
}
|
||||
});
|
||||
s.on('error', function (msg) { disconnectTunnel(this.tcp, this, 'Websocket error'); });
|
||||
s.on('close', function (msg) { disconnectTunnel(this.tcp, this, 'Websocket closed'); });
|
||||
s.parent = this;
|
||||
}
|
||||
|
||||
// Try to discover the location of the mesh server
|
||||
function discoverMeshServer() { console.log('Looking for server...'); discoveryInterval = setInterval(discoverMeshServerOnce, 5000); discoverMeshServerOnce(); }
|
||||
|
||||
// Try to discover the location of the mesh server only once
|
||||
function discoverMeshServerOnce() {
|
||||
var interfaces = os.networkInterfaces();
|
||||
for (var adapter in interfaces) {
|
||||
if (interfaces.hasOwnProperty(adapter)) {
|
||||
for (var i = 0 ; i < interfaces[adapter].length; ++i) {
|
||||
var addr = interfaces[adapter][i];
|
||||
multicastSockets[i] = dgram.createSocket({ type: (addr.family == "IPv4" ? "udp4" : "udp6") });
|
||||
multicastSockets[i].bind({ address: addr.address, exclusive: false });
|
||||
if (addr.family == "IPv4") {
|
||||
multicastSockets[i].addMembership(membershipIPv4);
|
||||
//multicastSockets[i].setMulticastLoopback(true);
|
||||
multicastSockets[i].once('message', OnMulticastMessage);
|
||||
multicastSockets[i].send(settings.serverId, 16989, membershipIPv4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Called when a multicast packet is received
|
||||
function OnMulticastMessage(msg, rinfo) {
|
||||
var m = msg.toString().split('|');
|
||||
if ((m.length == 3) && (m[0] == 'MeshCentral2') && (m[1] == settings.serverId)) {
|
||||
settings.serverUrl = m[2].replace('%s', rinfo.address).replace('/agent.ashx', '/meshrelay.ashx');
|
||||
console.log('Found server at ' + settings.serverUrl + '.');
|
||||
if (discoveryInterval != null) { clearInterval(discoveryInterval); discoveryInterval = null; }
|
||||
startRouter();
|
||||
}
|
||||
}
|
||||
|
||||
try { run(process.argv); } catch (e) { /*console.log(e);*/ }
|
|
@ -59,7 +59,7 @@ CheckInstallAgent() {
|
|||
DownloadAgent $url $meshid $machineid
|
||||
fi
|
||||
else
|
||||
echo "MeshID is not correct, must be 64 HEX characters long."
|
||||
echo "MeshID is not correct, must be 64 characters long."
|
||||
fi
|
||||
else
|
||||
echo "URI and/or MeshID have not been specified, must be passed in as arguments."
|
||||
|
@ -78,7 +78,7 @@ DownloadAgent() {
|
|||
wget $url/meshagents?id=$machineid -q --no-check-certificate -O /usr/local/mesh/meshagent
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
echo "Mesh agent download."
|
||||
echo "Mesh agent downloaded."
|
||||
# TODO: We could check the meshagent sha256 hash, but best to authenticate the server.
|
||||
chmod 755 /usr/local/mesh/meshagent
|
||||
wget $url/meshsettings?id=$meshid -q --no-check-certificate -O /usr/local/mesh/meshagent.msh
|
||||
|
@ -97,6 +97,7 @@ DownloadAgent() {
|
|||
ln -s /usr/local/mesh/meshagent /etc/rc3.d/S20mesh
|
||||
ln -s /usr/local/mesh/meshagent /etc/rc5.d/S20mesh
|
||||
fi
|
||||
echo "Mesh agent started."
|
||||
else
|
||||
echo "Unable to download mesh settings at: $url/meshsettings?id=$meshid."
|
||||
fi
|
||||
|
|
|
@ -131,7 +131,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||
if (len == agentUpdateBlockSize) { obj.ws.send(obj.agentUpdate.buf); } else { obj.ws.send(obj.agentUpdate.buf.slice(0, len + 4)); } // Command 14, mesh agent next data block
|
||||
|
||||
if (len < agentUpdateBlockSize) {
|
||||
console.log("Agent update sent");
|
||||
//console.log("Agent update sent");
|
||||
obj.send(obj.common.ShortToStr(13) + obj.common.ShortToStr(0) + obj.common.hex2rstr(obj.agentExeInfo.hash)); // Command 13, end mesh agent download, send agent SHA384 hash
|
||||
obj.fs.close(obj.agentUpdate.fd);
|
||||
obj.agentUpdate = null;
|
||||
|
|
29
meshrelay.js
29
meshrelay.js
|
@ -4,7 +4,7 @@
|
|||
* @version v0.0.1
|
||||
*/
|
||||
|
||||
module.exports.CreateMeshRelay = function (parent, ws, req) {
|
||||
module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
|
||||
var obj = {};
|
||||
obj.ws = ws;
|
||||
obj.req = req;
|
||||
|
@ -12,6 +12,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req) {
|
|||
obj.parent = parent;
|
||||
obj.id = req.query.id;
|
||||
obj.remoteaddr = obj.ws._socket.remoteAddress;
|
||||
obj.domain = domain;
|
||||
if (obj.remoteaddr.startsWith('::ffff:')) { obj.remoteaddr = obj.remoteaddr.substring(7); }
|
||||
|
||||
// Disconnect this agent
|
||||
|
@ -60,7 +61,27 @@ module.exports.CreateMeshRelay = function (parent, ws, req) {
|
|||
|
||||
if (req.query.auth == null) {
|
||||
// Use ExpressJS session, check if this session is a logged in user, at least one of the two connections will need to be authenticated.
|
||||
try { if ((req.session) && (req.session.userid) || (req.session.domainid == getDomain(req).id)) { obj.authenticated = true; } } catch (e) { }
|
||||
try { if ((req.session) && (req.session.userid) || (req.session.domainid == obj.domain.id)) { obj.authenticated = true; } } catch (e) { }
|
||||
if ((obj.authenticated != true) && (req.query.user != null) && (req.query.pass != null)) {
|
||||
// Check user authentication
|
||||
obj.parent.authenticate(req.query.user, req.query.pass, obj.domain, function (err, userid, passhint) {
|
||||
if (userid != null) {
|
||||
obj.authenticated = true;
|
||||
// Check is we have agent routing instructions, process this here.
|
||||
if ((req.query.nodeid != null) && (req.query.tcpport != null)) {
|
||||
if (obj.id == undefined) { obj.id = ('' + Math.random()).substring(2); } // If there is no connection id, generate one.
|
||||
var command = { nodeid: req.query.nodeid, action: 'msg', type: 'tunnel', value: '*/meshrelay.ashx?id=' + obj.id, tcpport: req.query.tcpport, tcpaddr: ((req.query.tcpaddr == null) ? '127.0.0.1' : req.query.tcpaddr) };
|
||||
if (obj.sendAgentMessage(command, userid, obj.domain.id) == false) { obj.id = null; obj.parent.parent.debug(1, 'Relay: Unable to contact this agent (' + obj.remoteaddr + ')'); }
|
||||
}
|
||||
} else {
|
||||
obj.parent.parent.debug(1, 'Relay: User authentication failed (' + obj.remoteaddr + ')');
|
||||
obj.ws.send('error:Authentication failed');
|
||||
}
|
||||
performRelay();
|
||||
});
|
||||
} else {
|
||||
performRelay();
|
||||
}
|
||||
} else {
|
||||
// Get the session from the cookie
|
||||
var cookie = obj.parent.parent.webserver.decodeCookie(req.query.auth);
|
||||
|
@ -76,9 +97,12 @@ module.exports.CreateMeshRelay = function (parent, ws, req) {
|
|||
} else {
|
||||
obj.id = null;
|
||||
obj.parent.parent.debug(1, 'Relay: invalid cookie (' + obj.remoteaddr + ')');
|
||||
obj.ws.send('error:Invalid cookie');
|
||||
}
|
||||
performRelay();
|
||||
}
|
||||
|
||||
function performRelay() {
|
||||
if (obj.id == null) { try { obj.close(); } catch (e) { } return null; } // Attempt to connect without id, drop this.
|
||||
ws._socket.setKeepAlive(true, 240000); // Set TCP keep alive
|
||||
|
||||
|
@ -148,6 +172,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ws.flushSink = function () {
|
||||
try { ws.resume(); } catch (e) { }
|
||||
|
|
|
@ -338,7 +338,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
|||
// TODO: Right now, we only create type 1 Agent-less Intel AMT mesh, or type 2 Agent mesh
|
||||
if ((command.meshtype == 1) || (command.meshtype == 2)) {
|
||||
// Create a type 1 agent-less Intel AMT mesh.
|
||||
obj.crypto.randomBytes(48, function (err, buf) {
|
||||
obj.parent.crypto.randomBytes(48, function (err, buf) {
|
||||
var meshid = 'mesh/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');;
|
||||
var links = {}
|
||||
links[user._id] = { name: user.name, rights: 0xFFFFFFFF };
|
||||
|
@ -492,7 +492,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
|||
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 4) == 0)) return;
|
||||
|
||||
// Create a new nodeid
|
||||
obj.crypto.randomBytes(48, function (err, buf) {
|
||||
obj.parent.crypto.randomBytes(48, function (err, buf) {
|
||||
// create the new node
|
||||
var nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');;
|
||||
var device = { type: 'node', mtype: 1, _id: nodeid, meshid: command.meshid, name: command.devicename, host: command.hostname, domain: domain.id, intelamt: { user: command.amtusername, pass: command.amtpassword, tls: parseInt(command.amttls) } };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.0.8-w",
|
||||
"version": "0.1.0-d",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
<script type="text/javascript" src="scripts/ol3-contextmenu.js"></script>
|
||||
<title>MeshCentral</title>
|
||||
</head>
|
||||
|
||||
<body onload="javascript:if (typeof(startup) !== 'undefined') startup();" oncontextmenu="handleContextMenu(event)">
|
||||
<!-- right click menu -->
|
||||
<div id="contextMenu" class="contextMenu" style="display: none">
|
||||
|
@ -1494,10 +1493,10 @@
|
|||
setDialogMode(2, "Add Mesh Agent", 1, null, x);
|
||||
|
||||
if (serverinfo.https == true) {
|
||||
Q('agins_linux_area').value = "wget -q https://" + serverinfo.name + ":" + serverinfo.port + "/meshagents?script=1 --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://" + serverinfo.name + ":" + serverinfo.port + " " + meshid.split('/')[2] + "\r\n";
|
||||
Q('agins_linux_area').value = "wget -q https://" + serverinfo.name + ":" + serverinfo.port + "/meshagents?script=1 --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://" + serverinfo.name + ":" + serverinfo.port + " " + meshid.split('/')[2].replace(/\$/g, '\\$') + "\r\n";
|
||||
Q('agins_linux_area_un').value = "wget -q https://" + serverinfo.name + ":" + serverinfo.port + "/meshagents?script=1 --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n";
|
||||
} else {
|
||||
Q('agins_linux_area').value = "wget -q http://" + serverinfo.name + ":" + serverinfo.port + "/meshagents?script=1 -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://" + serverinfo.name + ":" + serverinfo.port + " " + meshid.split('/')[2] + "\r\n";
|
||||
Q('agins_linux_area').value = "wget -q http://" + serverinfo.name + ":" + serverinfo.port + "/meshagents?script=1 -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://" + serverinfo.name + ":" + serverinfo.port + " " + meshid.split('/')[2].replace(/\$/g, '\\$') + "\r\n";
|
||||
Q('agins_linux_area_un').value = "wget -q http://" + serverinfo.name + ":" + serverinfo.port + "/meshagents?script=1 -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n";
|
||||
}
|
||||
}
|
||||
|
@ -2415,6 +2414,8 @@
|
|||
if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showNodeNetInfoDialog("' + node._id + '") title="Show device network interface information">Interfaces</a> ';
|
||||
if (xxmap != null) x += '<a style=cursor:pointer onclick=p10showNodeLocationDialog("' + node._id + '") title="Show device locations information">Location</a> ';
|
||||
|
||||
if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showRouterDialog("' + node._id + '") title="Traffic router used to connect to a device thru this server.">Router</a> ';
|
||||
|
||||
// RDP link, show this link only of the remote machine is Windows.
|
||||
if (((connectivity & 1) != 0) && (clickOnce == true) && (mesh.mtype == 2) && ((meshrights & 8) != 0)) {
|
||||
if ((node.agent.id > 0) && (node.agent.id < 5)) { x += '<a style=cursor:pointer onclick=p10clickOnce("' + node._id + '","RDP2",3389) title="Requires Microsoft ClickOnce support in your browser.">RDP</a> '; }
|
||||
|
@ -2689,6 +2690,39 @@
|
|||
meshserver.Send({ action: 'getnetworkinfo', nodeid: currentNode._id });
|
||||
}
|
||||
|
||||
// Show router dialog
|
||||
function p10showRouterDialog() {
|
||||
if (xxdialogMode) return;
|
||||
var y = "<select id=aginsSelect onclick=meshCmdOsClick() style=width:236px>";
|
||||
y += "<option value=1>Windows (32bit)</option>";
|
||||
y += "<option value=2>Windows (64bit)</option>";
|
||||
y += "<option value=5>Linux x86 (32bit)</option>";
|
||||
y += "<option value=6>Linux x86 (64bit)</option>";
|
||||
y += "<option value=25>Linux ARM, Raspberry Pi (32bit)</option>";
|
||||
y += "</select>";
|
||||
|
||||
var x = "";
|
||||
x += "<div>Download \"meshcmd\" with an action file to route traffic thru this server to this device. Make sure to edit meshaction.txt and add your account password or make any changes needed.<br /><br />";
|
||||
x += addHtmlValue('Operating System', y);
|
||||
x += addHtmlValue('Mesh Command', '<a id="meshcmddownloadid" href="meshagents?meshcmd=1" target="_blank"></a>');
|
||||
x += addHtmlValue('Action File', '<a href="meshagents?meshaction=route&nodeid=' + currentNode._id + '" target="_blank">MeshAction (.txt)</a>');
|
||||
x += "</div>";
|
||||
|
||||
setDialogMode(2, "Network Router", 1, null, x, currentNode._id);
|
||||
meshCmdOsClick();
|
||||
}
|
||||
|
||||
function meshCmdOsClick() {
|
||||
var os = Q('aginsSelect').value, osn = '';
|
||||
Q('meshcmddownloadid').href = "meshagents?meshcmd=" + os;
|
||||
if (os == 1) { osn = 'MeshCmd (Win32 executable)'; }
|
||||
if (os == 2) { osn = 'MeshCmd (Win64 executable)'; }
|
||||
if (os == 5) { osn = 'MeshCmd (Linux x86, 32bit)'; }
|
||||
if (os == 6) { osn = 'MeshCmd (Linux x86, 64bit)'; }
|
||||
if (os == 25) { osn = 'MeshCmd (Linux ARM, 32bit)'; }
|
||||
QH('meshcmddownloadid', osn);
|
||||
}
|
||||
|
||||
function p10showiconselector() {
|
||||
if (xxdialogMode) return;
|
||||
var mesh = meshes[currentNode.meshid];
|
||||
|
|
47
webserver.js
47
webserver.js
|
@ -88,6 +88,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
|
|||
// Perform hash on web certificate and agent certificate
|
||||
obj.webCertificateHash = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.web.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' });
|
||||
obj.webCertificateHashBase64 = new Buffer(parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.web.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' }), 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||
obj.agentCertificateHashHex = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.agent.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'hex' });
|
||||
obj.agentCertificateHashBase64 = new Buffer(parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.agent.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' }), 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||
obj.agentCertificateAsn1 = parent.certificateOperations.forge.asn1.toDer(parent.certificateOperations.forge.pki.certificateToAsn1(parent.certificateOperations.forge.pki.certificateFromPem(parent.certificates.agent.cert))).getBytes();
|
||||
|
||||
|
@ -1119,6 +1120,48 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
|
|||
if (scriptInfo == null) { res.sendStatus(404); return; }
|
||||
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename=' + scriptInfo.rname });
|
||||
res.sendFile(scriptInfo.path);
|
||||
} else if (req.query.meshcmd != null) {
|
||||
// Send meshcmd for a specific platform back
|
||||
var argentInfo = obj.parent.meshAgentBinaries[req.query.meshcmd];
|
||||
if (argentInfo == null) { res.sendStatus(404); return; }
|
||||
// Load the agent
|
||||
obj.fs.readFile(argentInfo.path, function (err, agentexe) {
|
||||
if (err != null) { res.sendStatus(404); return; }
|
||||
// Load meshcmd.js
|
||||
obj.fs.readFile(obj.path.join(__dirname, 'agents', 'meshcmd.js'), function (err, meshcmdjs) {
|
||||
if (err != null) { res.sendStatus(404); return; }
|
||||
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') });
|
||||
var tail = new Buffer(8);
|
||||
tail.writeInt32BE(meshcmdjs.length, 0);
|
||||
tail.writeInt32BE(agentexe.length + meshcmdjs.length + 8, 4);
|
||||
res.send(Buffer.concat([agentexe, meshcmdjs, tail]));
|
||||
});
|
||||
});
|
||||
} else if (req.query.meshaction != null) {
|
||||
var domain = checkUserIpAddress(req, res);
|
||||
var user = obj.users[req.session.userid];
|
||||
if (domain == null || req.query.nodeid == null) { res.sendStatus(404); return; }
|
||||
obj.db.Get(req.query.nodeid, function (err, nodes) {
|
||||
if (nodes.length != 1) { res.sendStatus(401); return; }
|
||||
var node = nodes[0];
|
||||
// Create the meshaction.txt file for meshcmd.exe
|
||||
var meshaction = {
|
||||
action: req.query.meshaction,
|
||||
localPort: 1234,
|
||||
remoteName: node.name,
|
||||
remoteNodeId: node._id,
|
||||
remotePort: 3389,
|
||||
username: '',
|
||||
password: '',
|
||||
serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key
|
||||
serverHttpsHash: new Buffer(obj.webCertificateHash, 'binary').toString('hex').toUpperCase(), // SHA384 of server HTTPS certificate
|
||||
debugLevel: 0
|
||||
}
|
||||
if (user != null) { meshaction.username = user.name; }
|
||||
if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + obj.certificates.CommonName + ':' + obj.args.port + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; }
|
||||
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename=meshaction.txt' });
|
||||
res.send(JSON.stringify(meshaction, null, ' '));
|
||||
});
|
||||
} else {
|
||||
// Send a list of available mesh agents
|
||||
var response = '<html><head><title>Mesh Agents</title><style>table,th,td { border:1px solid black;border-collapse:collapse;padding:3px; }</style></head><body><table>';
|
||||
|
@ -1140,7 +1183,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
|
|||
if (domain == null) return;
|
||||
//if ((domain.id !== '') || (!req.session) || (req.session == null) || (!req.session.userid)) { res.sendStatus(401); return; }
|
||||
|
||||
// Delete a mesh and all computers within it
|
||||
// Query the meshid
|
||||
obj.db.Get('mesh/' + domain.id + '/' + req.query.id, function (err, meshes) {
|
||||
if (meshes.length != 1) { res.sendStatus(401); return; }
|
||||
var mesh = meshes[0];
|
||||
|
@ -1205,7 +1248,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
|
|||
obj.app.post(url + 'uploadmeshcorefile.ashx', handleUploadMeshCoreFile);
|
||||
obj.app.get(url + 'userfiles/*', handleDownloadUserFiles);
|
||||
obj.app.ws(url + 'echo.ashx', handleEchoWebSocket);
|
||||
obj.app.ws(url + 'meshrelay.ashx', function (ws, req) { try { obj.meshRelayHandler.CreateMeshRelay(obj, ws, req); } catch (e) { console.log(e); } });
|
||||
obj.app.ws(url + 'meshrelay.ashx', function (ws, req) { try { obj.meshRelayHandler.CreateMeshRelay(obj, ws, req, getDomain(req)); } catch (e) { console.log(e); } });
|
||||
|
||||
// Receive mesh agent connections
|
||||
obj.app.ws(url + 'agent.ashx', function (ws, req) { try { var domain = getDomain(req); obj.meshAgentHandler.CreateMeshAgent(obj, obj.db, ws, req, obj.args, domain); } catch (e) { console.log(e); } });
|
||||
|
|
Loading…
Reference in a new issue